Neutralize accidental @everyone/@here in outbound agent text
Agent-authored replies pass through sanitizeForOutbound before Discord send, but it did not touch mass-mention tokens — so a reply that merely *mentioned* "@everyone" while explaining a feature pinged the whole channel. Add neutralizeMassMentions (zero-width space after @) to the central sanitizer so normal reply/progress/edit text can never mass-ping; intentional broadcasts (e.g. the disk-usage alert) use a dedicated path. Leaves <@id> mentions and emails intact. Covered by unit tests. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -146,10 +146,24 @@ export function neutralizeStrayMarkdown(text: string): string {
|
||||
/** @deprecated Kept for back-compat; use neutralizeStrayMarkdown. */
|
||||
export const neutralizeStrayBackticks = neutralizeStrayMarkdown;
|
||||
|
||||
/**
|
||||
* Prevent accidental mass pings. Agent-authored text that literally contains
|
||||
* `@everyone` / `@here` must never notify the whole channel — that is only ever
|
||||
* intended via a dedicated broadcast path (e.g. the disk-usage alert), not via a
|
||||
* normal reply/progress/edit message. A zero-width space (U+200B) after the `@`
|
||||
* keeps the text readable ("@everyone" still reads the same) while stopping
|
||||
* Discord from parsing it as a mention. Idempotent, and leaves `<@id>` user/role
|
||||
* mentions and ordinary emails (`me@example.com`) untouched.
|
||||
*/
|
||||
export function neutralizeMassMentions(text: string): string {
|
||||
return text.replace(/@(everyone|here)\b/g, '@\u200b$1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize raw agent output for internal use (storage, IPC, intermediate
|
||||
* channel buffers). Strips internal tags + tool-call leaks and redacts
|
||||
* secrets, but does NOT touch markdown delimiters.
|
||||
* channel buffers). Strips internal tags + tool-call leaks, redacts secrets,
|
||||
* and neutralizes accidental @everyone/@here pings, but does NOT touch markdown
|
||||
* delimiters.
|
||||
*
|
||||
* Use this when the text will pass through another `formatOutbound` call
|
||||
* downstream (e.g., the Discord channel boundary). Applying the markdown
|
||||
@@ -161,7 +175,8 @@ export function sanitizeForOutbound(rawText: string): string {
|
||||
if (!text) return '';
|
||||
text = stripToolCallLeaks(text);
|
||||
if (!text) return '';
|
||||
return redactSecrets(text);
|
||||
text = redactSecrets(text);
|
||||
return neutralizeMassMentions(text);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user