fix: suppress reasoning payload leakage in whatsapp replies

This commit is contained in:
Peter Steinberger
2026-02-25 01:36:19 +00:00
parent a177b10b79
commit 039713c3e7
3 changed files with 68 additions and 0 deletions

View File

@@ -70,6 +70,56 @@ const replyLogger = {
};
describe("deliverWebReply", () => {
it("suppresses payloads flagged as reasoning", async () => {
const msg = makeMsg();
await deliverWebReply({
replyResult: { text: "Reasoning:\n_hidden_", isReasoning: true },
msg,
maxMediaBytes: 1024 * 1024,
textLimit: 200,
replyLogger,
skipLog: true,
});
expect(msg.reply).not.toHaveBeenCalled();
expect(msg.sendMedia).not.toHaveBeenCalled();
});
it("suppresses payloads that start with reasoning prefix text", async () => {
const msg = makeMsg();
await deliverWebReply({
replyResult: { text: " \n Reasoning:\n_hidden_" },
msg,
maxMediaBytes: 1024 * 1024,
textLimit: 200,
replyLogger,
skipLog: true,
});
expect(msg.reply).not.toHaveBeenCalled();
expect(msg.sendMedia).not.toHaveBeenCalled();
});
it("does not suppress messages that mention Reasoning: mid-text", async () => {
const msg = makeMsg();
await deliverWebReply({
replyResult: { text: "Intro line\nReasoning: appears in content but is not a prefix" },
msg,
maxMediaBytes: 1024 * 1024,
textLimit: 200,
replyLogger,
skipLog: true,
});
expect(msg.reply).toHaveBeenCalledTimes(1);
expect(msg.reply).toHaveBeenCalledWith(
"Intro line\nReasoning: appears in content but is not a prefix",
);
});
it("sends chunked text replies and logs a summary", async () => {
const msg = makeMsg();

View File

@@ -12,6 +12,19 @@ import { whatsappOutboundLog } from "./loggers.js";
import type { WebInboundMsg } from "./types.js";
import { elide } from "./util.js";
const REASONING_PREFIX = "reasoning:";
function shouldSuppressReasoningReply(payload: ReplyPayload): boolean {
if (payload.isReasoning === true) {
return true;
}
const text = payload.text;
if (typeof text !== "string") {
return false;
}
return text.trimStart().toLowerCase().startsWith(REASONING_PREFIX);
}
export async function deliverWebReply(params: {
replyResult: ReplyPayload;
msg: WebInboundMsg;
@@ -29,6 +42,10 @@ export async function deliverWebReply(params: {
}) {
const { replyResult, msg, maxMediaBytes, textLimit, replyLogger, connectionId, skipLog } = params;
const replyStarted = Date.now();
if (shouldSuppressReasoningReply(replyResult)) {
whatsappOutboundLog.debug(`Suppressed reasoning payload to ${msg.from}`);
return;
}
const tableMode = params.tableMode ?? "code";
const chunkMode = params.chunkMode ?? "length";
const convertedText = markdownToWhatsApp(