Files
Visigine/server/lib/monitoring/detect-mention.js
Ihor_Zhekov e344f1b7e7 Initial commit: Visigine (Vite client + Express/SQLite backend)
Container-ready via docker/ compose (frontend nginx + backend Node). Compose adjusted for Coolify on the prod server: frontend uses expose:80 (no host binding — host 8080 is taken by the Coolify proxy; Traefik routes visigine.de), backend ALLOWED_ORIGINS=https://visigine.de. Secrets stay in server/.env (git-ignored); see server/.env.example.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 10:15:06 +02:00

39 lines
1.3 KiB
JavaScript

// Case-insensitive substring search for brand identifiers in LLM output.
// Returns the first match's position and a ~200-char surrounding snippet.
export function detectMention(text, client) {
let aliases = []
try { aliases = JSON.parse(client.brand_aliases || '[]') } catch { /* keep [] */ }
const candidates = [
client.name,
client.hostname?.split('.')[0],
...aliases,
]
.filter(Boolean)
.map((s) => String(s).toLowerCase().trim())
.filter((s) => s.length >= 3)
.filter((v, i, a) => a.indexOf(v) === i)
if (!text || candidates.length === 0) {
return { mentioned: false, position: null, snippet: null }
}
const lower = text.toLowerCase()
let best = null
for (const candidate of candidates) {
const idx = lower.indexOf(candidate)
if (idx >= 0 && (best === null || idx < best.position)) {
best = { position: idx, candidate }
}
}
if (!best) return { mentioned: false, position: null, snippet: null }
const start = Math.max(0, best.position - 100)
const end = Math.min(text.length, best.position + best.candidate.length + 100)
let snippet = text.slice(start, end).trim()
if (start > 0) snippet = '…' + snippet
if (end < text.length) snippet = snippet + '…'
return { mentioned: true, position: best.position, snippet }
}