diff --git a/src/LibraryManager.jsx b/src/LibraryManager.jsx index c1544c8..3abe083 100644 --- a/src/LibraryManager.jsx +++ b/src/LibraryManager.jsx @@ -19,7 +19,7 @@ function itemSyncMeta(item) { status, progress: 100, label: 'Available', - detail: detail || (enrichEnabled ? 'Ready in chat with enrichment enabled.' : 'Ready in chat with raw indexing only.') + detail: detail || (enrichEnabled ? 'Ready with standard metadata and deep enrichment.' : 'Ready with standard metadata.') } } if (status === 'failed') { @@ -287,7 +287,17 @@ export default function LibraryManager({ apiBase, library, jobs, onRefresh }) { body: JSON.stringify({ rel: item.rel, enabled }) }) return expectJson(response) - }) + }, enabled ? 'Deep enrichment enabled. Metadata is being updated.' : 'Using standard metadata only.') + } catch {} + } + + async function generateMetadata() { + if (!library) return + try { + await runAction(async () => { + const response = await fetch(`${apiBase}/libraries/${library.slug}/jobs/prepare`, { method: 'POST' }) + return expectJson(response) + }, 'Generating metadata for this database.') } catch {} } @@ -311,9 +321,20 @@ export default function LibraryManager({ apiBase, library, jobs, onRefresh }) { const filteredItems = useMemo(() => { const term = search.trim().toLowerCase() if (!term) return items - return items.filter(item => [item.title, item.name, item.path, item.url, item.kind] + return items.filter(item => [ + item.title, + item.name, + item.path, + item.url, + item.kind, + item.metadata?.headline, + item.metadata?.summary, + ...(item.metadata?.keywords || []), + ...(item.metadata?.entities || []).map(entity => entity?.name) + ] .some(value => String(value || '').toLowerCase().includes(term))) }, [items, search]) + const hasMissingMetadata = items.some(item => !['ready', 'fallback'].includes(item?.metadata?.status)) useEffect(() => { if (!library?.slug) { @@ -415,6 +436,9 @@ export default function LibraryManager({ apiBase, library, jobs, onRefresh }) { const itemId = item.item_id || item.sha256 || item.rel const isExpanded = expandedItemId === itemId const preview = contentPreviews[itemId] + const metadata = item.metadata || {} + const keywords = Array.isArray(metadata.keywords) ? metadata.keywords.slice(0, 6) : [] + const entities = Array.isArray(metadata.entities) ? metadata.entities.slice(0, 4) : [] return (
@@ -424,7 +448,29 @@ export default function LibraryManager({ apiBase, library, jobs, onRefresh }) {
{item.title || item.name || item.path}
{source}
- {item.enrich_enabled ? 'Enrichment on' : 'Raw only'} + {item.enrich_enabled ? 'Deep enrichment' : 'Standard'} +
+
+ {metadata.summary ? ( +

{metadata.summary}

+ ) : ( +

+ {metadata.status === 'pending' ? 'Metadata is being generated.' : 'No automatic metadata has been generated yet.'} +

+ )} + {keywords.length > 0 && ( +
+ {keywords.map(keyword => {keyword})} +
+ )} + {entities.length > 0 && ( +
+ {entities.map(entity => ( + {entity.name}{entity.type ? ` ยท ${entity.type}` : ''} + ))} +
+ )} + {metadata.status === 'fallback' &&
Local model metadata was unavailable; Heimgeist used a text fallback.
}
{sync.detail}
@@ -456,7 +502,7 @@ export default function LibraryManager({ apiBase, library, jobs, onRefresh }) { {item.kind === 'website' && } {(!item.kind || item.kind === 'file') && }
@@ -473,6 +519,9 @@ export default function LibraryManager({ apiBase, library, jobs, onRefresh }) { + {items.length > 0 && hasMissingMetadata && !isSyncing && isReadyForChat && ( + + )} {items.length > 0 && !isSyncing && !isReadyForChat && ( )}