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({ 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 = { 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 { const { searchResults } = useSearchContext(); const result: Array = []; 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; }