mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-29 22:58:51 +01:00
feat: add file search capability to ephemeral agents, update code interpreter selection based of file upload, consolidate main upload menu for all endpoints
This commit is contained in:
parent
13c977a670
commit
ef7e517c06
5 changed files with 36 additions and 25 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <AttachFileMenu disabled={disableInputs} />;
|
||||
}
|
||||
if (endpointSupportsFiles && !isUploadDisabled) {
|
||||
return <AttachFile disabled={disableInputs} />;
|
||||
return <AttachFileMenu disabled={disableInputs} conversationId={conversationId} />;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -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<HTMLInputElement>(null);
|
||||
const [isPopoverActive, setIsPopoverActive] = useState(false);
|
||||
const setEphemeralAgent = useSetRecoilState(ephemeralAgentByConvoId(conversationId));
|
||||
const [toolResource, setToolResource] = useState<EToolResources | undefined>();
|
||||
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: <FileSearch className="icon-md" />,
|
||||
|
|
@ -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: <TerminalSquareIcon className="icon-md" />,
|
||||
|
|
@ -87,7 +99,7 @@ const AttachFile = ({ disabled }: AttachFileProps) => {
|
|||
}
|
||||
|
||||
return items;
|
||||
}, [capabilities, localize, setToolResource]);
|
||||
}, [capabilities, localize, setToolResource, setEphemeralAgent]);
|
||||
|
||||
const menuTrigger = (
|
||||
<TooltipAnchor
|
||||
|
|
@ -132,4 +144,4 @@ const AttachFile = ({ disabled }: AttachFileProps) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default React.memo(AttachFile);
|
||||
export default React.memo(AttachFileMenu);
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ export type TEndpointOption = Pick<
|
|||
export type TEphemeralAgent = {
|
||||
mcp?: string[];
|
||||
web_search?: boolean;
|
||||
file_search?: boolean;
|
||||
execute_code?: boolean;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue