feat: Gitea Webhook, IMAP, Settings & Deployment docs
- Webhook route and Gitea integration - IMAP service and Nextcloud/Porkbun setup docs - Settings UI improvements and API updates - SSH/Webhook fix prompt for emailsorter.webklar.com - Bootstrap, config and AI sorter updates
This commit is contained in:
@@ -417,7 +417,8 @@ Subject: ${subject}
|
||||
Preview: ${snippet?.substring(0, 500) || 'No preview'}
|
||||
|
||||
RESPONSE FORMAT (JSON ONLY):
|
||||
{"category": "category_key", "confidence": 0.0-1.0, "reason": "brief explanation"}
|
||||
{"category": "category_key", "confidence": 0.0-1.0, "reason": "brief explanation", "assignedTo": "name_label_id_or_name_or_null"}
|
||||
If the email is clearly FOR a specific worker (e.g. "für Max", "an Anna", subject/body mentions them), set assignedTo to that worker's id or name. Otherwise set assignedTo to null or omit it.
|
||||
|
||||
Respond ONLY with the JSON object.`
|
||||
|
||||
@@ -438,6 +439,15 @@ Respond ONLY with the JSON object.`
|
||||
result.category = 'review'
|
||||
}
|
||||
|
||||
// Validate assignedTo against name labels (id or name)
|
||||
if (result.assignedTo && preferences.nameLabels?.length) {
|
||||
const match = preferences.nameLabels.find(
|
||||
l => l.enabled && (l.id === result.assignedTo || l.name === result.assignedTo)
|
||||
)
|
||||
if (!match) result.assignedTo = null
|
||||
else result.assignedTo = match.id || match.name
|
||||
}
|
||||
|
||||
return result
|
||||
} catch (error) {
|
||||
log.error('AI categorization failed', { error: error.message })
|
||||
@@ -484,7 +494,8 @@ EMAILS:
|
||||
${emailList}
|
||||
|
||||
RESPONSE FORMAT (JSON ARRAY ONLY):
|
||||
[{"index": 0, "category": "key"}, {"index": 1, "category": "key"}, ...]
|
||||
[{"index": 0, "category": "key", "assignedTo": "id_or_name_or_null"}, ...]
|
||||
If an email is clearly FOR a specific worker, set assignedTo to that worker's id or name. Otherwise omit or null.
|
||||
|
||||
Respond ONLY with the JSON array.`
|
||||
|
||||
@@ -515,9 +526,16 @@ Respond ONLY with the JSON array.`
|
||||
return emails.map((email, i) => {
|
||||
const result = parsed.find(r => r.index === i)
|
||||
const category = result?.category && CATEGORIES[result.category] ? result.category : 'review'
|
||||
let assignedTo = result?.assignedTo || null
|
||||
if (assignedTo && preferences.nameLabels?.length) {
|
||||
const match = preferences.nameLabels.find(
|
||||
l => l.enabled && (l.id === assignedTo || l.name === assignedTo)
|
||||
)
|
||||
assignedTo = match ? (match.id || match.name) : null
|
||||
}
|
||||
return {
|
||||
email,
|
||||
classification: { category, confidence: 0.8, reason: 'Batch' },
|
||||
classification: { category, confidence: 0.8, reason: 'Batch', assignedTo },
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
@@ -578,6 +596,14 @@ Respond ONLY with the JSON array.`
|
||||
}
|
||||
}
|
||||
|
||||
// Name labels (workers) – assign email to a person when clearly for them
|
||||
if (preferences.nameLabels?.length) {
|
||||
const activeNameLabels = preferences.nameLabels.filter(l => l.enabled)
|
||||
if (activeNameLabels.length > 0) {
|
||||
parts.push(`NAME LABELS (workers) – assign email to ONE person when the email is clearly FOR that person (e.g. "für Max", "an Anna", "Max bitte prüfen", subject/body mentions them):\n${activeNameLabels.map(l => `- id: "${l.id}", name: "${l.name}"${l.keywords?.length ? `, keywords: ${JSON.stringify(l.keywords)}` : ''}`).join('\n')}\nIf the email is for a specific worker, set "assignedTo" to that label's id or name. Otherwise omit assignedTo.`)
|
||||
}
|
||||
}
|
||||
|
||||
return parts.length > 0 ? `USER PREFERENCES:\n${parts.join('\n')}\n` : ''
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user