From 2a98fd3d0b8e34bee71c2f41abd2d34ee7cdd5fa Mon Sep 17 00:00:00 2001 From: stone-jin <1520006273@qq.com> Date: Tue, 3 Mar 2026 00:02:48 +0800 Subject: [PATCH] fix(slack): guard against undefined text in includes calls during mention handling --- src/auto-reply/reply/mentions.test.ts | 20 ++++++++++++++++++++ src/auto-reply/reply/mentions.ts | 3 +++ src/slack/format.test.ts | 4 ++++ src/slack/format.ts | 6 ++++++ 4 files changed, 33 insertions(+) create mode 100644 src/auto-reply/reply/mentions.test.ts diff --git a/src/auto-reply/reply/mentions.test.ts b/src/auto-reply/reply/mentions.test.ts new file mode 100644 index 00000000000..833f0b0c524 --- /dev/null +++ b/src/auto-reply/reply/mentions.test.ts @@ -0,0 +1,20 @@ +import { describe, expect, it } from "vitest"; +import { stripStructuralPrefixes } from "./mentions.js"; + +describe("stripStructuralPrefixes", () => { + it("returns empty string for undefined input at runtime", () => { + expect(stripStructuralPrefixes(undefined as unknown as string)).toBe(""); + }); + + it("returns empty string for empty input", () => { + expect(stripStructuralPrefixes("")).toBe(""); + }); + + it("strips sender prefix labels", () => { + expect(stripStructuralPrefixes("John: hello")).toBe("hello"); + }); + + it("passes through plain text", () => { + expect(stripStructuralPrefixes("just a message")).toBe("just a message"); + }); +}); diff --git a/src/auto-reply/reply/mentions.ts b/src/auto-reply/reply/mentions.ts index 3081517c65d..4c8aca16998 100644 --- a/src/auto-reply/reply/mentions.ts +++ b/src/auto-reply/reply/mentions.ts @@ -111,6 +111,9 @@ export function matchesMentionWithExplicit(params: { } export function stripStructuralPrefixes(text: string): string { + if (!text) { + return ""; + } // Ignore wrapper labels, timestamps, and sender prefixes so directive-only // detection still works in group batches that include history/context. const afterMarker = text.includes(CURRENT_MESSAGE_MARKER) diff --git a/src/slack/format.test.ts b/src/slack/format.test.ts index bb2003e2cd4..220fa7a594c 100644 --- a/src/slack/format.test.ts +++ b/src/slack/format.test.ts @@ -57,6 +57,10 @@ describe("markdownToSlackMrkdwn", () => { "*Important:* Check the _docs_ at \n\n• first\n• second", ); }); + + it("does not throw when input is undefined at runtime", () => { + expect(markdownToSlackMrkdwn(undefined as unknown as string)).toBe(""); + }); }); describe("escapeSlackMrkdwn", () => { diff --git a/src/slack/format.ts b/src/slack/format.ts index 3b07bd66d04..2eade04153f 100644 --- a/src/slack/format.ts +++ b/src/slack/format.ts @@ -28,6 +28,9 @@ function isAllowedSlackAngleToken(token: string): boolean { } function escapeSlackMrkdwnContent(text: string): string { + if (!text) { + return ""; + } if (!text.includes("&") && !text.includes("<") && !text.includes(">")) { return text; } @@ -53,6 +56,9 @@ function escapeSlackMrkdwnContent(text: string): string { } function escapeSlackMrkdwnText(text: string): string { + if (!text) { + return ""; + } if (!text.includes("&") && !text.includes("<") && !text.includes(">")) { return text; }