Skip to content

Commit 2f2110a

Browse files
HALobviyus
authored andcommitted
fix: tighten isSilentReplyText to match whole-text only
The suffix regex matched NO_REPLY at the end of any response, suppressing substantive replies when models (e.g. Gemini 3 Pro) appended NO_REPLY to real content. Replace prefix+suffix regexes with a single whole-string match. Only responses that are entirely the silent token (with optional whitespace) are now suppressed. Add unit tests for the fix. Fixes #19537
1 parent a7d56e3 commit 2f2110a

2 files changed

Lines changed: 41 additions & 6 deletions

File tree

src/auto-reply/tokens.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { describe, it, expect } from "vitest";
2+
import { isSilentReplyText } from "./tokens.js";
3+
4+
describe("isSilentReplyText", () => {
5+
it("returns true for exact token", () => {
6+
expect(isSilentReplyText("NO_REPLY")).toBe(true);
7+
});
8+
9+
it("returns true for token with surrounding whitespace", () => {
10+
expect(isSilentReplyText(" NO_REPLY ")).toBe(true);
11+
expect(isSilentReplyText("\nNO_REPLY\n")).toBe(true);
12+
});
13+
14+
it("returns false for undefined/empty", () => {
15+
expect(isSilentReplyText(undefined)).toBe(false);
16+
expect(isSilentReplyText("")).toBe(false);
17+
});
18+
19+
it("returns false for substantive text ending with token (#19537)", () => {
20+
const text = "Here is a helpful response.\n\nNO_REPLY";
21+
expect(isSilentReplyText(text)).toBe(false);
22+
});
23+
24+
it("returns false for substantive text starting with token", () => {
25+
const text = "NO_REPLY but here is more content";
26+
expect(isSilentReplyText(text)).toBe(false);
27+
});
28+
29+
it("returns false for token embedded in text", () => {
30+
expect(isSilentReplyText("Please NO_REPLY to this")).toBe(false);
31+
});
32+
33+
it("works with custom token", () => {
34+
expect(isSilentReplyText("HEARTBEAT_OK", "HEARTBEAT_OK")).toBe(true);
35+
expect(isSilentReplyText("Checked inbox. HEARTBEAT_OK", "HEARTBEAT_OK")).toBe(false);
36+
});
37+
});

src/auto-reply/tokens.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,10 @@ export function isSilentReplyText(
1111
return false;
1212
}
1313
const escaped = escapeRegExp(token);
14-
const prefix = new RegExp(`^\\s*${escaped}(?=$|\\W)`);
15-
if (prefix.test(text)) {
16-
return true;
17-
}
18-
const suffix = new RegExp(`\\b${escaped}\\b\\W*$`);
19-
return suffix.test(text);
14+
// Only match when the entire response (trimmed) is the silent token,
15+
// optionally surrounded by whitespace/punctuation. This prevents
16+
// substantive replies ending with NO_REPLY from being suppressed (#19537).
17+
return new RegExp(`^\\s*${escaped}\\s*$`).test(text);
2018
}
2119

2220
export function isSilentReplyPrefixText(

0 commit comments

Comments
 (0)