fix: chat "this note" context searches all notes + Ollama model selector missing search

- When chat scope is "this note" (noteContext present), skip RAG/semantic
  search entirely. Previously the AI received all user notes as context
  even when scoped to a single note, causing irrelevant responses.
- Replace 3 native <select> elements for Ollama models with searchable
  Combobox component (tags, embeddings, chat providers).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-30 19:04:34 +02:00
parent 43f73a2ec7
commit cd6819b905
2 changed files with 80 additions and 92 deletions

View File

@@ -446,27 +446,21 @@ export function AdminSettingsForm({ config }: { config: Record<string, string> }
</div>
</div>
<div className="space-y-2">
<Label htmlFor="AI_MODEL_TAGS_OLLAMA">{t('admin.ai.model')}</Label>
<select
id="AI_MODEL_TAGS_OLLAMA"
name="AI_MODEL_TAGS_OLLAMA"
<Label>{t('admin.ai.model')}</Label>
<input type="hidden" name="AI_MODEL_TAGS_OLLAMA" value={selectedTagsModel} />
<Combobox
options={ollamaTagsModels.length > 0
? ollamaTagsModels.map((m) => ({ value: m, label: m }))
: selectedTagsModel
? [{ value: selectedTagsModel, label: `${selectedTagsModel} (${t('admin.ai.saved')})` }]
: []
}
value={selectedTagsModel}
onChange={(e) => setSelectedTagsModel(e.target.value)}
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
>
{ollamaTagsModels.length > 0 ? (
<>
{!ollamaTagsModels.includes(selectedTagsModel) && selectedTagsModel && (
<option value={selectedTagsModel}>{selectedTagsModel} ({t('admin.ai.configured')})</option>
)}
{ollamaTagsModels.map((model) => (
<option key={model} value={model}>{model}</option>
))}
</>
) : (
<option value={selectedTagsModel || 'granite4:latest'}>{selectedTagsModel || 'granite4:latest'} {t('admin.ai.saved')}</option>
)}
</select>
onChange={setSelectedTagsModel}
placeholder={selectedTagsModel || t('admin.ai.clickToLoadModels')}
searchPlaceholder={t('admin.ai.searchModel')}
emptyMessage={t('admin.ai.noModels')}
/>
<p className="text-xs text-muted-foreground">
{isLoadingTagsModels ? t('admin.ai.fetchingModels') : t('admin.ai.selectOllamaModel')}
</p>
@@ -620,27 +614,21 @@ export function AdminSettingsForm({ config }: { config: Record<string, string> }
</div>
</div>
<div className="space-y-2">
<Label htmlFor="AI_MODEL_EMBEDDING_OLLAMA">{t('admin.ai.model')}</Label>
<select
id="AI_MODEL_EMBEDDING_OLLAMA"
name="AI_MODEL_EMBEDDING_OLLAMA"
<Label>{t('admin.ai.model')}</Label>
<input type="hidden" name="AI_MODEL_EMBEDDING_OLLAMA" value={selectedEmbeddingModel} />
<Combobox
options={ollamaEmbeddingsModels.length > 0
? ollamaEmbeddingsModels.map((m) => ({ value: m, label: m }))
: selectedEmbeddingModel
? [{ value: selectedEmbeddingModel, label: `${selectedEmbeddingModel} (${t('admin.ai.saved')})` }]
: []
}
value={selectedEmbeddingModel}
onChange={(e) => setSelectedEmbeddingModel(e.target.value)}
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
>
{ollamaEmbeddingsModels.length > 0 ? (
<>
{!ollamaEmbeddingsModels.includes(selectedEmbeddingModel) && selectedEmbeddingModel && (
<option value={selectedEmbeddingModel}>{selectedEmbeddingModel} ({t('admin.ai.configured')})</option>
)}
{ollamaEmbeddingsModels.map((model) => (
<option key={model} value={model}>{model}</option>
))}
</>
) : (
<option value={selectedEmbeddingModel || 'embeddinggemma:latest'}>{selectedEmbeddingModel || 'embeddinggemma:latest'} {t('admin.ai.saved')}</option>
)}
</select>
onChange={setSelectedEmbeddingModel}
placeholder={selectedEmbeddingModel || t('admin.ai.clickToLoadModels')}
searchPlaceholder={t('admin.ai.searchModel')}
emptyMessage={t('admin.ai.noModels')}
/>
<p className="text-xs text-muted-foreground">
{isLoadingEmbeddingsModels ? t('admin.ai.fetchingModels') : t('admin.ai.selectEmbeddingModel')}
</p>
@@ -790,27 +778,21 @@ export function AdminSettingsForm({ config }: { config: Record<string, string> }
</div>
</div>
<div className="space-y-2">
<Label htmlFor="AI_MODEL_CHAT_OLLAMA">{t('admin.ai.model')}</Label>
<select
id="AI_MODEL_CHAT_OLLAMA"
name="AI_MODEL_CHAT_OLLAMA"
<Label>{t('admin.ai.model')}</Label>
<input type="hidden" name="AI_MODEL_CHAT_OLLAMA" value={selectedChatModel} />
<Combobox
options={ollamaChatModels.length > 0
? ollamaChatModels.map((m) => ({ value: m, label: m }))
: selectedChatModel
? [{ value: selectedChatModel, label: `${selectedChatModel} (${t('admin.ai.saved')})` }]
: []
}
value={selectedChatModel}
onChange={(e) => setSelectedChatModel(e.target.value)}
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
>
{ollamaChatModels.length > 0 ? (
<>
{!ollamaChatModels.includes(selectedChatModel) && selectedChatModel && (
<option value={selectedChatModel}>{selectedChatModel} ({t('admin.ai.configured')})</option>
)}
{ollamaChatModels.map((model) => (
<option key={model} value={model}>{model}</option>
))}
</>
) : (
<option value={selectedChatModel || 'granite4:latest'}>{selectedChatModel || 'granite4:latest'} {t('admin.ai.saved')}</option>
)}
</select>
onChange={setSelectedChatModel}
placeholder={selectedChatModel || t('admin.ai.clickToLoadModels')}
searchPlaceholder={t('admin.ai.searchModel')}
emptyMessage={t('admin.ai.noModels')}
/>
<p className="text-xs text-muted-foreground">
{isLoadingChatModels ? t('admin.ai.fetchingModels') : t('admin.ai.selectOllamaModel')}
</p>