import type { ModelState } from '../types'; interface ModelStatusProps { models: ModelState[]; } const STATUS_COLOR: Record = { pending: '#9e9e9e', downloading: '#1976d2', loading: '#f9a825', ready: '#388e3c', error: '#d32f2f', }; const STATUS_LABEL: Record = { pending: 'Pending', downloading: 'Downloading', loading: 'Loading', ready: 'Ready', error: 'Error', }; function ProgressBar({ progress, color }: { progress: number; color: string }) { return (
); } function ModelRow({ model }: { model: ModelState }) { const color = STATUS_COLOR[model.status]; const showProgress = model.status === 'downloading' || model.status === 'loading'; return (
{model.name} {model.status === 'ready' && ( {'\u2713'} )} {model.status === 'error' && ( {'\u2717'} )} {STATUS_LABEL[model.status]} {showProgress && ( {Math.round(model.progress * 100)}% )}
{showProgress && } {model.status === 'error' && model.error && (
{model.error}
)}
); } export default function ModelStatus({ models }: ModelStatusProps) { const coreModels = models.filter((model) => model.name !== 'expansion'); const expansionModel = models.find((model) => model.name === 'expansion'); const coreReady = coreModels.length > 0 && coreModels.every((model) => model.status === 'ready'); const expansionReady = expansionModel?.status === 'ready'; const expansionUnavailable = expansionModel?.status === 'error'; return (

Models

{coreReady && ( Search ready )}
{!coreReady && (

First load downloads several GB of model weights. Subsequent visits use the browser cache.

)} {coreReady && !expansionReady && !expansionUnavailable && (

Embedding and reranker ready. Compact expansion model (single-file download) loading...

)} {coreReady && expansionUnavailable && (

Expansion model unavailable. Search uses the original query directly.

)} {models.map(m => ( ))} {models.length === 0 && (
No models configured.
)}
); }