mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-04-07 00:15:23 +02:00
Merge 3803a76095 into 8ed0bcf5ca
This commit is contained in:
commit
dd7224b44c
4 changed files with 110 additions and 1 deletions
|
|
@ -21,6 +21,7 @@ import FileSearch from './FileSearch';
|
|||
import Artifacts from './Artifacts';
|
||||
import MCPSelect from './MCPSelect';
|
||||
import WebSearch from './WebSearch';
|
||||
import NativeWebSearch from './NativeWebSearch';
|
||||
import store from '~/store';
|
||||
|
||||
interface BadgeRowProps {
|
||||
|
|
@ -371,6 +372,7 @@ function BadgeRow({
|
|||
{showEphemeralBadges === true && (
|
||||
<>
|
||||
<WebSearch />
|
||||
<NativeWebSearch />
|
||||
<CodeInterpreter />
|
||||
<FileSearch />
|
||||
<Artifacts />
|
||||
|
|
|
|||
57
client/src/components/Chat/Input/NativeWebSearch.tsx
Normal file
57
client/src/components/Chat/Input/NativeWebSearch.tsx
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import React, { memo } from 'react';
|
||||
import { Globe } from 'lucide-react';
|
||||
import { CheckboxButton } from '@librechat/client';
|
||||
import { LocalStorageKeys, Permissions, PermissionTypes } from 'librechat-data-provider';
|
||||
import { useLocalize, useSetIndexOptions, useHasAccess } from '~/hooks';
|
||||
import useLocalStorage from '~/hooks/useLocalStorageAlt';
|
||||
import { useChatContext } from '~/Providers/ChatContext';
|
||||
|
||||
function NativeWebSearch() {
|
||||
const localize = useLocalize();
|
||||
const { setOption } = useSetIndexOptions();
|
||||
const { conversation } = useChatContext();
|
||||
const [isPinned] = useLocalStorage<boolean>(
|
||||
`${LocalStorageKeys.LAST_NATIVE_WEB_SEARCH_TOGGLE_}pinned`,
|
||||
false,
|
||||
);
|
||||
|
||||
// Only show native web search if user doesn't have permission for authenticated web search
|
||||
const canUseWebSearch = useHasAccess({
|
||||
permissionType: PermissionTypes.WEB_SEARCH,
|
||||
permission: Permissions.USE,
|
||||
});
|
||||
|
||||
// Don't render if user has access to authenticated web search
|
||||
if (canUseWebSearch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Use conversation.web_search as the single source of truth
|
||||
const webSearchEnabled = conversation?.web_search ?? false;
|
||||
|
||||
// Don't render if not enabled and not pinned
|
||||
if (!webSearchEnabled && !isPinned) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const handleChange = (values: {
|
||||
e?: React.ChangeEvent<HTMLInputElement>;
|
||||
value: string | boolean;
|
||||
}) => {
|
||||
const checked = typeof values.value === 'boolean' ? values.value : values.value === 'true';
|
||||
setOption('web_search')(checked);
|
||||
};
|
||||
|
||||
return (
|
||||
<CheckboxButton
|
||||
className="max-w-fit"
|
||||
checked={webSearchEnabled}
|
||||
setValue={handleChange}
|
||||
label={localize('com_ui_web_search')}
|
||||
isCheckedClassName="border-purple-600/40 bg-purple-500/10 hover:bg-purple-700/10"
|
||||
icon={<Globe className="icon-md" />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default memo(NativeWebSearch);
|
||||
|
|
@ -8,13 +8,16 @@ import {
|
|||
Permissions,
|
||||
ArtifactModes,
|
||||
PermissionTypes,
|
||||
LocalStorageKeys,
|
||||
defaultAgentCapabilities,
|
||||
} from 'librechat-data-provider';
|
||||
import { useLocalize, useHasAccess, useAgentCapabilities } from '~/hooks';
|
||||
import { useLocalize, useHasAccess, useAgentCapabilities, useSetIndexOptions } from '~/hooks';
|
||||
import ArtifactsSubMenu from '~/components/Chat/Input/ArtifactsSubMenu';
|
||||
import MCPSubMenu from '~/components/Chat/Input/MCPSubMenu';
|
||||
import { useGetStartupConfig } from '~/data-provider';
|
||||
import { useBadgeRowContext } from '~/Providers';
|
||||
import { useChatContext } from '~/Providers/ChatContext';
|
||||
import useLocalStorage from '~/hooks/useLocalStorageAlt';
|
||||
import { cn } from '~/utils';
|
||||
|
||||
interface ToolsDropdownProps {
|
||||
|
|
@ -36,6 +39,8 @@ const ToolsDropdown = ({ disabled }: ToolsDropdownProps) => {
|
|||
searchApiKeyForm,
|
||||
} = useBadgeRowContext();
|
||||
const { data: startupConfig } = useGetStartupConfig();
|
||||
const { conversation } = useChatContext();
|
||||
const { setOption } = useSetIndexOptions();
|
||||
|
||||
const { codeEnabled, webSearchEnabled, artifactsEnabled, fileSearchEnabled } =
|
||||
useAgentCapabilities(agentsConfig?.capabilities ?? defaultAgentCapabilities);
|
||||
|
|
@ -49,6 +54,10 @@ const ToolsDropdown = ({ disabled }: ToolsDropdownProps) => {
|
|||
setIsPinned: setIsSearchPinned,
|
||||
authData: webSearchAuthData,
|
||||
} = webSearch;
|
||||
const [isNativeWebSearchPinned, setIsNativeWebSearchPinned] = useLocalStorage<boolean>(
|
||||
`${LocalStorageKeys.LAST_NATIVE_WEB_SEARCH_TOGGLE_}pinned`,
|
||||
false,
|
||||
);
|
||||
const {
|
||||
isPinned: isCodePinned,
|
||||
setIsPinned: setIsCodePinned,
|
||||
|
|
@ -77,6 +86,8 @@ const ToolsDropdown = ({ disabled }: ToolsDropdownProps) => {
|
|||
permission: Permissions.USE,
|
||||
});
|
||||
|
||||
const shouldShowNativeWebSearch = !canUseWebSearch;
|
||||
|
||||
const showWebSearchSettings = useMemo(() => {
|
||||
const authTypes = webSearchAuthData?.authTypes ?? [];
|
||||
if (authTypes.length === 0) return true;
|
||||
|
|
@ -93,6 +104,11 @@ const ToolsDropdown = ({ disabled }: ToolsDropdownProps) => {
|
|||
webSearch.debouncedChange({ value: newValue });
|
||||
}, [webSearch]);
|
||||
|
||||
const handleNativeWebSearchToggle = useCallback(() => {
|
||||
const currentValue = conversation?.web_search ?? false;
|
||||
setOption('web_search')(!currentValue);
|
||||
}, [conversation?.web_search, setOption]);
|
||||
|
||||
const handleCodeInterpreterToggle = useCallback(() => {
|
||||
const newValue = !codeInterpreter.toggleState;
|
||||
codeInterpreter.debouncedChange({ value: newValue });
|
||||
|
|
@ -220,6 +236,38 @@ const ToolsDropdown = ({ disabled }: ToolsDropdownProps) => {
|
|||
});
|
||||
}
|
||||
|
||||
if (shouldShowNativeWebSearch) {
|
||||
dropdownItems.push({
|
||||
onClick: handleNativeWebSearchToggle,
|
||||
hideOnClick: false,
|
||||
render: (props) => (
|
||||
<div {...props}>
|
||||
<div className="flex items-center gap-2">
|
||||
<Globe className="icon-md" />
|
||||
<span>{localize('com_ui_web_search')}</span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setIsNativeWebSearchPinned(!isNativeWebSearchPinned);
|
||||
}}
|
||||
className={cn(
|
||||
'rounded p-1 transition-all duration-200',
|
||||
'hover:bg-surface-secondary hover:shadow-sm',
|
||||
!isNativeWebSearchPinned && 'text-text-secondary hover:text-text-primary',
|
||||
)}
|
||||
aria-label={isNativeWebSearchPinned ? localize('com_ui_unpin') : localize('com_ui_pin')}
|
||||
>
|
||||
<div className="h-4 w-4">
|
||||
<PinIcon unpin={isNativeWebSearchPinned} />
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
if (canRunCode && codeEnabled) {
|
||||
dropdownItems.push({
|
||||
onClick: handleCodeInterpreterToggle,
|
||||
|
|
|
|||
|
|
@ -1931,6 +1931,8 @@ export enum LocalStorageKeys {
|
|||
LAST_CODE_TOGGLE_ = 'LAST_CODE_TOGGLE_',
|
||||
/** Last checked toggle for Web Search per conversation ID */
|
||||
LAST_WEB_SEARCH_TOGGLE_ = 'LAST_WEB_SEARCH_TOGGLE_',
|
||||
/** Last checked toggle for Native Web Search per conversation ID */
|
||||
LAST_NATIVE_WEB_SEARCH_TOGGLE_ = 'LAST_NATIVE_WEB_SEARCH_TOGGLE_',
|
||||
/** Last checked toggle for File Search per conversation ID */
|
||||
LAST_FILE_SEARCH_TOGGLE_ = 'LAST_FILE_SEARCH_TOGGLE_',
|
||||
/** Last checked toggle for Artifacts per conversation ID */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue