'use client'; /** * Query Tester Component * * Allows testing search queries against the memory system * with detailed score breakdowns and explanations. */ import { useState } from 'react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Memory } from '@/types/memory'; const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001'; interface SearchResult { memory: Memory & { decayedScore: number }; relevanceScore: number; } type SearchMode = 'hybrid' | 'fts' | 'vector'; export function QueryTester() { const [query, setQuery] = useState(''); const [mode, setMode] = useState('hybrid'); const [results, setResults] = useState([]); const [isSearching, setIsSearching] = useState(false); const [error, setError] = useState(null); const handleSearch = async () => { if (!query.trim()) return; setIsSearching(true); setError(null); try { const params = new URLSearchParams({ query: query.trim(), mode: 'search', limit: '20', }); const response = await fetch(`${API_BASE}/api/memories?${params}`); if (!response.ok) { throw new Error(`Search failed: ${response.statusText}`); } const data = await response.json(); // Transform API response to include relevance score const resultsWithScore: SearchResult[] = data.memories.map((m: Memory & { decayedScore: number }) => ({ memory: m, relevanceScore: m.decayedScore, // Using decayedScore as proxy for relevance })); setResults(resultsWithScore); } catch (err) { setError((err as Error).message); setResults([]); } finally { setIsSearching(false); } }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { handleSearch(); } }; return (
{/* Search Controls */}
setQuery(e.target.value)} onKeyDown={handleKeyDown} className="flex-1 bg-slate-800 border-slate-600 text-white" /> {/* Mode Toggle */}
{(['hybrid', 'fts', 'vector'] as SearchMode[]).map((m) => ( ))}
{/* Results */}
{error && (
{error}
)} {results.length === 0 && !error && (
{query ? 'No results found' : 'Enter a query to search memories'}
)} {results.length > 0 && (
Found {results.length} results
{results.map((result, index) => ( ))}
Title Score Type Category
{index + 1}. {result.memory.title}
{(result.relevanceScore * 100).toFixed(0)}%
{result.memory.type.replace('_', '-')} {result.memory.category}
)}
); }