← Back to PRs

#19916: fix: strict silent-reply detection to prevent false positives with CJK text

by hayoial open 2026-02-18 09:16 View on GitHub →
size: S
## Summary **Problem:** `isSilentReplyText()` uses `\b` and `\W` regex anchors to detect silent reply tokens (NO_REPLY, HEARTBEAT_OK). In JavaScript, `\W` matches any non-`[a-zA-Z0-9_]` character — including all CJK (Chinese/Japanese/Korean) characters. This causes any assistant reply containing `NO_REPLY` followed by CJK text to be falsely detected as a silent reply and silently swallowed. **Why it matters:** CJK-language users lose messages. The assistant generates a valid reply mentioning NO_REPLY in context, but it never gets delivered. This is a data-loss bug affecting all CJK locales across all channels (Discord, Telegram, Slack, etc.). **What changed:** Replace the regex-based detection with strict `text.trim() === token` comparison. The system prompt already instructs the model to reply with ONLY `NO_REPLY` as the entire message, so partial matching is unnecessary and harmful. ## Changes - `src/auto-reply/tokens.ts`: Replace regex with `text.trim() === token` (7 lines removed, 1 added) - `src/auto-reply/tokens.test.ts`: New test file with 10 cases covering exact match, whitespace, CJK, English sentences, substrings, and custom tokens ## Validation Evidence Tested locally with 18 cases before this PR (on a running OpenClaw instance): ``` ✅ "NO_REPLY" → true ✅ " NO_REPLY " → true ✅ "NO_REPLY 这是中文消息" → false (was: true — the bug) ✅ "中文消息 NO_REPLY" → false (was: true) ✅ "中文NO_REPLY消息" → false (was: true) ✅ "Here is NO_REPLY for you" → false ✅ undefined → false ✅ "" → false ``` ## Security Impact - **Risk:** None - No new dependencies, no network changes, no permission changes - Strictly reduces false positives (fewer messages silently dropped) ## Privacy and Data Hygiene - No PII involved - Fix *prevents* message loss (improves data delivery) ## Rollback Plan - Revert single commit to restore regex-based detection - No migrations or config changes <!-- greptile_comment --> <h3>Greptile Summary</h3> Fixes a data-loss bug where `isSilentReplyText()` used `\b` and `\W` regex anchors that matched CJK characters as word boundaries, causing valid assistant replies containing `NO_REPLY` alongside CJK text to be silently swallowed. The fix replaces the regex with a strict `text.trim() === token` equality check, which aligns with the system prompt's instruction that `NO_REPLY` must be the model's entire message. - **Bug fix**: `\W` in JavaScript matches all non-ASCII characters including CJK, so `NO_REPLY` followed by Chinese/Japanese/Korean text was falsely detected as a silent reply - **Approach**: Strict equality after trimming — simple, correct, and well-aligned with the system prompt contract ("It must be your ENTIRE message — nothing else") - **Tests**: New test file with 10 cases covering exact match, whitespace, CJK text, English sentences, substrings, and custom tokens - **Minor issue**: Unused `escapeRegExp` import left in `tokens.ts` (line 1) — should be removed to pass linting <h3>Confidence Score: 4/5</h3> - This PR is safe to merge after removing the unused import — it's a well-scoped bug fix with good test coverage. - The logic change is correct and well-justified: strict equality matching aligns with the system prompt contract. The only issue is a leftover unused import that will likely fail linting. All 14 call sites were reviewed and none rely on the old partial-matching behavior. - `src/auto-reply/tokens.ts` has an unused `escapeRegExp` import on line 1 that needs to be removed. <sub>Last reviewed commit: 6ff6717</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs