From 75f358001b28418626af86b098f8ad43e3b3db8a Mon Sep 17 00:00:00 2001 From: zhi Date: Fri, 27 Feb 2026 15:20:05 +0000 Subject: [PATCH] fix(rules): handle multi-byte emoji in getLastChar via Array.from MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit getLastChar used t[t.length-1] which only gets the trailing surrogate of emoji like 🔚 (U+1F51A, a surrogate pair in UTF-16). This meant end symbol matching ALWAYS failed for emoji symbols, causing every non-humanList message to hit rule_match_no_end_symbol -> no-reply. Fix: use Array.from(t) to correctly split by Unicode code points. --- plugin/rules.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugin/rules.ts b/plugin/rules.ts index 1a69b44..ca00593 100644 --- a/plugin/rules.ts +++ b/plugin/rules.ts @@ -43,7 +43,10 @@ function stripTrailingMetadata(input: string): string { function getLastChar(input: string): string { const t = stripTrailingMetadata(input).trim(); - return t.length ? t[t.length - 1] : ""; + if (!t.length) return ""; + // Use Array.from to handle multi-byte characters (emoji, surrogate pairs) + const chars = Array.from(t); + return chars[chars.length - 1] || ""; } export function resolvePolicy(config: WhisperGateConfig, channelId?: string, channelPolicies?: Record) {