'use client'; import React, { useState } from 'react'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { useTranslation } from 'react-i18next'; import { RetrieveResult } from '@/app/infra/entities/api'; import { toast } from 'sonner'; interface KBRetrieveGenericProps { kbId: string; retrieveFunction: ( kbId: string, query: string, ) => Promise<{ results: RetrieveResult[] }>; getResultTitle?: (result: RetrieveResult) => string; } /** * Generic knowledge base retrieve component * Supports both builtin and external knowledge bases */ export default function KBRetrieveGeneric({ kbId, retrieveFunction, getResultTitle, }: KBRetrieveGenericProps) { const { t } = useTranslation(); const [query, setQuery] = useState(''); const [results, setResults] = useState([]); const [loading, setLoading] = useState(false); const handleRetrieve = async () => { if (!query.trim()) return; setLoading(true); try { setResults([]); const response = await retrieveFunction(kbId, query); setResults(response.results); } catch (error) { console.error('Retrieve failed:', error); toast.error(t('knowledge.retrieveError')); } finally { setLoading(false); } }; const getTitle = (result: RetrieveResult): string => { if (getResultTitle) { return getResultTitle(result); } // Default: use file_id or document_name from metadata return ( (result.metadata.file_id as string) || (result.metadata.document_name as string) || result.id ); }; /** * Extract text content from the content array * The content array may contain multiple items with type 'text' */ const extractTextFromContent = (result: RetrieveResult): string => { // First try to get content from the new format if (result.content && Array.isArray(result.content)) { const textParts = result.content .filter((item) => item.type === 'text' && item.text) .map((item) => item.text); if (textParts.length > 0) { return textParts.join('\n\n'); } } return ''; }; return (
setQuery(e.target.value)} placeholder={t('knowledge.queryPlaceholder')} onKeyPress={(e) => e.key === 'Enter' && handleRetrieve()} />
{results.length === 0 && !loading && (

{t('knowledge.noResults')}

)} {loading ? (

{t('common.loading')}

) : ( results.map((result) => ( {getTitle(result)} {t('knowledge.distance')}: {result.distance.toFixed(4)}

{extractTextFromContent(result)}

)) )}
); }