| import { createContext, useContext } from 'react'; | |
| import type { SearchRefType, ValidSource, ResultReference } from 'librechat-data-provider'; | |
| import type * as t from './types'; | |
| import { useSearchContext } from '~/Providers'; | |
| export interface CitationContextType { | |
| hoveredCitationId: string | null; | |
| setHoveredCitationId: (id: string | null) => void; | |
| } | |
| export const CitationContext = createContext<CitationContextType>({ | |
| hoveredCitationId: null, | |
| setHoveredCitationId: () => {}, | |
| }); | |
| export function useHighlightState(citationId: string | undefined) { | |
| const { hoveredCitationId } = useContext(CitationContext); | |
| return citationId && hoveredCitationId === citationId; | |
| } | |
| export type CitationSource = (ValidSource | ResultReference) & { | |
| turn: number; | |
| refType: string | SearchRefType; | |
| index: number; | |
| }; | |
| const refTypeMap: Record<string | SearchRefType, string> = { | |
| search: 'organic', | |
| ref: 'references', | |
| news: 'topStories', | |
| file: 'references', | |
| }; | |
| export function useCitation({ | |
| turn, | |
| index, | |
| refType: _refType, | |
| }: { | |
| turn: number; | |
| index: number; | |
| refType?: SearchRefType | string; | |
| }): (t.Citation & t.Reference) | undefined { | |
| const { searchResults } = useSearchContext(); | |
| if (!_refType) { | |
| return undefined; | |
| } | |
| const refType = refTypeMap[_refType.toLowerCase()] | |
| ? refTypeMap[_refType.toLowerCase()] | |
| : _refType; | |
| if (!searchResults || !searchResults[turn] || !searchResults[turn][refType]) { | |
| return undefined; | |
| } | |
| const source: CitationSource = searchResults[turn][refType][index]; | |
| if (!source) { | |
| return undefined; | |
| } | |
| return { | |
| ...source, | |
| turn, | |
| refType: _refType.toLowerCase(), | |
| index, | |
| link: source.link ?? '', | |
| title: source.title ?? '', | |
| snippet: source['snippet'] ?? '', | |
| attribution: source.attribution ?? '', | |
| }; | |
| } | |
| export function useCompositeCitations( | |
| citations: Array<{ turn: number; refType: SearchRefType | string; index: number }>, | |
| ): Array<t.Citation & t.Reference> { | |
| const { searchResults } = useSearchContext(); | |
| const result: Array<t.Citation & t.Reference> = []; | |
| for (const { turn, refType: _refType, index } of citations) { | |
| const refType = refTypeMap[_refType.toLowerCase()] | |
| ? refTypeMap[_refType.toLowerCase()] | |
| : _refType; | |
| if (!searchResults || !searchResults[turn] || !searchResults[turn][refType]) { | |
| continue; | |
| } | |
| const source: CitationSource = searchResults[turn][refType][index]; | |
| if (!source) { | |
| continue; | |
| } | |
| result.push({ | |
| ...source, | |
| turn, | |
| refType: _refType.toLowerCase(), | |
| index, | |
| link: source.link ?? '', | |
| title: source.title ?? '', | |
| snippet: source['snippet'] ?? '', | |
| attribution: source.attribution ?? '', | |
| }); | |
| } | |
| return result; | |
| } | |