Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion backend/brain-prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,40 @@ function timeAgo(ts: number): string {
return `${days}d ago`;
}

// Promo / routine notification sender patterns. Used to drop noise participants
// from the active-threads surface — many of these accumulate under a single
// gmail:<account> thread key and crowd out real conversations. Raw observations
// remain logged; only the prompt-side aggregation is filtered.
const PROMO_LOCAL_PATTERNS: RegExp[] = [
/no-?reply@/i,
/do-?not-?reply@/i,
/newsletter@/i,
/notifications?@/i,
/savedsearches?@/i,
/jobalerts(?:-noreply)?@/i,
/best-message-notice@/i,
];

const PROMO_DOMAIN_KEYWORDS: string[] = [
"aliexpress",
"autoscout24",
"glassdoor",
"ferrari",
"mijn.overheid",
"marktplaats",
"quora",
];

function isPromoSender(sender: string): boolean {
if (!sender) return false;
const match = /<([^>]+)>/.exec(sender);
const addr = (match ? match[1] : sender).trim().toLowerCase();
if (PROMO_LOCAL_PATTERNS.some(re => re.test(addr))) return true;
const domain = addr.includes("@") ? addr.split("@")[1] || "" : addr;
if (PROMO_DOMAIN_KEYWORDS.some(kw => domain.includes(kw))) return true;
return false;
}

function formatSingleObservation(obs: Observation): string {
const time = formatTime(obs.timestamp);
const who = obs.isFromMe ? `${obs.sender || "Me"} (you/outgoing)` : obs.sender || "Unknown";
Expand Down Expand Up @@ -318,7 +352,19 @@ function formatWorkingMemory(wm: WorkingMemory): string {

// Active conversation threads
if (wm.conversationThreads && wm.conversationThreads.length > 0) {
const activeThreads = wm.conversationThreads.filter(t => t.status === "active").slice(0, 5);
const activeThreads = wm.conversationThreads
.filter(t => t.status === "active")
// Drop promo/notification senders from participants. If a thread is
// entirely promo (e.g. the gmail:<account> bucket where unrelated
// newsletters pile up), suppress it entirely.
.map(t => {
const filtered = Array.isArray(t.participants)
? t.participants.filter(p => !isPromoSender(p))
: t.participants;
return { ...t, participants: filtered };
})
.filter(t => Array.isArray(t.participants) ? t.participants.length > 0 : !!t.participants)
.slice(0, 5);
if (activeThreads.length > 0) {
const threadLines = activeThreads.map(t => {
const who = Array.isArray(t.participants) ? t.participants.join(", ") : (t.participants || "unknown");
Expand Down