mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-23 10:46:12 +01:00
92 lines
2.7 KiB
TypeScript
92 lines
2.7 KiB
TypeScript
|
|
import { useMemo } from 'react';
|
||
|
|
import type { TAttachment } from 'librechat-data-provider';
|
||
|
|
import { StackedFavicons } from '~/components/Web/Sources';
|
||
|
|
import { useSearchContext } from '~/Providers';
|
||
|
|
import ProgressText from './ProgressText';
|
||
|
|
import { useLocalize } from '~/hooks';
|
||
|
|
|
||
|
|
type ProgressKeys =
|
||
|
|
| 'com_ui_web_searching'
|
||
|
|
| 'com_ui_web_searching_again'
|
||
|
|
| 'com_ui_web_search_processing'
|
||
|
|
| 'com_ui_web_search_reading';
|
||
|
|
|
||
|
|
export default function WebSearch({
|
||
|
|
initialProgress: progress = 0.1,
|
||
|
|
isSubmitting,
|
||
|
|
isLast,
|
||
|
|
output,
|
||
|
|
}: {
|
||
|
|
isLast?: boolean;
|
||
|
|
isSubmitting: boolean;
|
||
|
|
output?: string | null;
|
||
|
|
initialProgress: number;
|
||
|
|
attachments?: TAttachment[];
|
||
|
|
}) {
|
||
|
|
const localize = useLocalize();
|
||
|
|
const { searchResults } = useSearchContext();
|
||
|
|
const error = typeof output === 'string' && output.toLowerCase().includes('error processing');
|
||
|
|
const cancelled = (!isSubmitting && progress < 1) || error === true;
|
||
|
|
|
||
|
|
const complete = !isLast && progress === 1;
|
||
|
|
const finalizing = isSubmitting && isLast && progress === 1;
|
||
|
|
const processedSources = useMemo(() => {
|
||
|
|
if (complete && !finalizing) {
|
||
|
|
return [];
|
||
|
|
}
|
||
|
|
if (!searchResults) return [];
|
||
|
|
const values = Object.values(searchResults);
|
||
|
|
const result = values[values.length - 1];
|
||
|
|
if (!result) return [];
|
||
|
|
if (finalizing) {
|
||
|
|
return [...(result.organic || []), ...(result.topStories || [])];
|
||
|
|
}
|
||
|
|
return [...(result.organic || []), ...(result.topStories || [])].filter(
|
||
|
|
(source) => source.processed === true,
|
||
|
|
);
|
||
|
|
}, [searchResults, complete, finalizing]);
|
||
|
|
const turns = useMemo(() => {
|
||
|
|
if (!searchResults) return 0;
|
||
|
|
return Object.values(searchResults).length;
|
||
|
|
}, [searchResults]);
|
||
|
|
|
||
|
|
const clampedProgress = useMemo(() => {
|
||
|
|
return Math.min(progress, 0.99);
|
||
|
|
}, [progress]);
|
||
|
|
|
||
|
|
const showSources = processedSources.length > 0;
|
||
|
|
const progressText = useMemo(() => {
|
||
|
|
let text: ProgressKeys = turns > 1 ? 'com_ui_web_searching_again' : 'com_ui_web_searching';
|
||
|
|
if (showSources) {
|
||
|
|
text = 'com_ui_web_search_processing';
|
||
|
|
}
|
||
|
|
if (finalizing) {
|
||
|
|
text = 'com_ui_web_search_reading';
|
||
|
|
}
|
||
|
|
return localize(text);
|
||
|
|
}, [turns, localize, showSources, finalizing]);
|
||
|
|
|
||
|
|
if (complete || cancelled) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
<div className="relative my-2.5 flex size-5 shrink-0 items-center gap-2.5">
|
||
|
|
{showSources && (
|
||
|
|
<div className="mr-2">
|
||
|
|
<StackedFavicons sources={processedSources} start={-5} />
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
<ProgressText
|
||
|
|
finishedText=""
|
||
|
|
hasInput={false}
|
||
|
|
error={cancelled}
|
||
|
|
isExpanded={false}
|
||
|
|
progress={clampedProgress}
|
||
|
|
inProgressText={progressText}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
</>
|
||
|
|
);
|
||
|
|
}
|