import { useMCP } from '@/hooks/useMCP' import { useEffect, useState } from 'react' import { DynamicFilters } from './DynamicFilters' import { SelectableTags } from './SelectableTags' import { CollectionMetadata } from '@/types/mcp' type Filter = { tags?: string[] source_ids?: string[] [key: string]: any } type SearchConfig = { previews: boolean useScores: boolean limit: number // Search enhancement options useBm25?: boolean useHyde?: boolean useReranking?: boolean useQueryAnalysis?: boolean } export interface SearchParams { query: string modalities: string[] filters: Filter config: SearchConfig } interface SearchFormProps { isLoading: boolean onSearch: (params: SearchParams) => void } // Pure helper functions for SearchForm const createFlags = (items: string[], defaultValue = false): Record => items.reduce((acc, item) => ({ ...acc, [item]: defaultValue }), {}) const getSelectedItems = (items: Record): string[] => Object.entries(items).filter(([_, selected]) => selected).map(([key]) => key) const cleanFilters = (filters: Record): Record => Object.entries(filters) .filter(([_, value]) => value !== null && value !== '' && value !== undefined) .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}) export const SearchForm = ({ isLoading, onSearch }: SearchFormProps) => { const [query, setQuery] = useState('') const [previews, setPreviews] = useState(false) const [useScores, setUseScores] = useState(false) const [modalities, setModalities] = useState>({}) const [schemas, setSchemas] = useState>({}) const [tags, setTags] = useState>({}) const [dynamicFilters, setDynamicFilters] = useState>({}) const [limit, setLimit] = useState(10) // Search enhancement options - initialize to match server defaults // All enabled by default (query analysis runs in parallel with HyDE, no extra latency) const [useBm25, setUseBm25] = useState(true) const [useHyde, setUseHyde] = useState(true) const [useReranking, setUseReranking] = useState(true) const [useQueryAnalysis, setUseQueryAnalysis] = useState(true) const { getMetadataSchemas, getTags } = useMCP() useEffect(() => { const setupFilters = async () => { const [schemas, tags] = await Promise.all([ getMetadataSchemas(), getTags() ]) setSchemas(schemas) setModalities(createFlags(Object.keys(schemas), true)) setTags(createFlags(tags)) } setupFilters() }, [getMetadataSchemas, getTags]) const handleFilterChange = (field: string, value: any) => setDynamicFilters(prev => ({ ...prev, [field]: value })) const handleSubmit = (e: React.FormEvent) => { e.preventDefault() onSearch({ query, modalities: getSelectedItems(modalities), config: { previews, useScores, limit, useBm25, useHyde, useReranking, useQueryAnalysis, }, filters: { tags: getSelectedItems(tags), ...cleanFilters(dynamicFilters) }, }) } return (
setQuery(e.target.value)} placeholder="Search your knowledge base..." className="search-input" required />
Search Enhancements
setModalities({ ...modalities, [tag]: selected })} onBatchUpdate={(updates) => setModalities(updates)} /> setTags({ ...tags, [tag]: selected })} onBatchUpdate={(updates) => setTags(updates)} searchable={true} />
) } export default SearchForm