fix: auto-tagging provider resolution, email test flow, language detection

Auto-tagging:
- CRITICAL FIX: contextual-auto-tag.service.ts was calling getAIProvider()
  (alias for getEmbeddingsProvider) instead of getTagsProvider(). This meant
  auto-tagging used the embeddings provider/model instead of the tags one.
  Now correctly uses getTagsProvider() in both suggestFromExistingLabels and
  suggestNewLabels methods.
- Pass user's detected language to suggestLabels() for localized prompts
  (was hardcoded to 'en')

Email:
- Fix Resend "from" field: pass DB config to sendViaResend() instead of
  re-fetching from DB. Uses SMTP_FROM from config, with localhost-aware fallback.
- Add "Sender email" field in admin Resend section so users can set SMTP_FROM
- Save SMTP_FROM when Resend is selected (was only saved for SMTP mode)
- Test email button now saves config to DB BEFORE testing, so unsaved form
  values are used (was reading stale DB values)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Sepehr Ramezani
2026-04-21 08:00:50 +02:00
parent d3c2de2000
commit d1cda126d8
4 changed files with 57 additions and 9 deletions

View File

@@ -277,6 +277,8 @@ export function AdminSettingsForm({ config }: { config: Record<string, string> }
if (emailProvider === 'resend') {
const key = formData.get('RESEND_API_KEY') as string
if (key) data.RESEND_API_KEY = key
const from = formData.get('SMTP_FROM') as string
if (from) data.SMTP_FROM = from
} else {
data.SMTP_HOST = formData.get('SMTP_HOST') as string
data.SMTP_PORT = formData.get('SMTP_PORT') as string
@@ -300,6 +302,32 @@ export function AdminSettingsForm({ config }: { config: Record<string, string> }
const handleTestEmail = async () => {
setIsTesting(true)
try {
// Save email config to DB first so test uses the latest values
const emailForm = document.querySelector('form[name="email-form"]') as HTMLFormElement
if (emailForm) {
const formData = new FormData(emailForm)
const saveData: Record<string, string> = { EMAIL_PROVIDER: emailProvider }
if (emailProvider === 'resend') {
const key = formData.get('RESEND_API_KEY') as string
if (key) saveData.RESEND_API_KEY = key
const from = formData.get('SMTP_FROM') as string
if (from) saveData.SMTP_FROM = from
} else {
saveData.SMTP_HOST = formData.get('SMTP_HOST') as string
saveData.SMTP_PORT = formData.get('SMTP_PORT') as string
saveData.SMTP_USER = formData.get('SMTP_USER') as string
saveData.SMTP_PASS = formData.get('SMTP_PASS') as string
saveData.SMTP_FROM = formData.get('SMTP_FROM') as string
saveData.SMTP_IGNORE_CERT = smtpIgnoreCert ? 'true' : 'false'
saveData.SMTP_SECURE = smtpSecure ? 'true' : 'false'
}
const saveResult = await updateSystemConfig(saveData)
if (saveResult.error) {
toast.error('Failed to save settings before testing: ' + saveResult.error)
setIsTesting(false)
return
}
}
const result: any = await testEmail(emailProvider)
if (result.success) {
toast.success(t('admin.smtp.testSuccess'))
@@ -892,7 +920,7 @@ export function AdminSettingsForm({ config }: { config: Record<string, string> }
<CardTitle>{t('admin.email.title')}</CardTitle>
<CardDescription>{t('admin.email.description')}</CardDescription>
</CardHeader>
<form onSubmit={(e) => { e.preventDefault(); handleSaveEmail(new FormData(e.currentTarget)) }}>
<form name="email-form" onSubmit={(e) => { e.preventDefault(); handleSaveEmail(new FormData(e.currentTarget)) }}>
<CardContent className="space-y-4">
<div className="space-y-2">
<label className="text-sm font-medium">{t('admin.email.provider')}</label>
@@ -957,6 +985,11 @@ export function AdminSettingsForm({ config }: { config: Record<string, string> }
<Input id="RESEND_API_KEY" name="RESEND_API_KEY" type="password" defaultValue={config.RESEND_API_KEY || ''} placeholder="re_..." />
<p className="text-xs text-muted-foreground">{t('admin.resend.apiKeyHint')}</p>
</div>
<div className="space-y-2">
<label htmlFor="SMTP_FROM_RESEND" className="text-sm font-medium">Sender email</label>
<Input id="SMTP_FROM_RESEND" name="SMTP_FROM" defaultValue={config.SMTP_FROM || ''} placeholder="noreply@yourdomain.com" />
<p className="text-xs text-muted-foreground">Email address used as sender. Must be a domain verified in Resend.</p>
</div>
{config.RESEND_API_KEY && (
<div className="flex items-center gap-2 text-xs text-green-600">
<span className="inline-block w-2 h-2 rounded-full bg-green-500" />

View File

@@ -509,10 +509,26 @@ export async function createNote(data: {
console.log('[BG] Auto-labeling check: enabled=', autoLabelingEnabled, 'confidence=', autoLabelingConfidence, 'notebookId=', notebookId)
if (autoLabelingEnabled) {
// Detect user's language from their existing notes for localized prompts
let userLang = 'en'
try {
const langResult = await prisma.note.groupBy({
by: ['language'],
where: { userId, language: { not: null } },
_count: true,
orderBy: { _count: { language: 'desc' } },
take: 1,
})
if (langResult.length > 0 && langResult[0].language) {
userLang = langResult[0].language
}
} catch {}
const suggestions = await contextualAutoTagService.suggestLabels(
content,
notebookId,
userId
userId,
userLang
)
console.log('[BG] Auto-labeling suggestions:', suggestions.length, suggestions.map(s => s.label))