fix: hide message_id hints in web chat

This commit is contained in:
Peter Steinberger
2026-01-24 13:52:27 +00:00
parent 386d21b6d1
commit 9d742ba51f
2 changed files with 54 additions and 3 deletions

View File

@@ -0,0 +1,42 @@
import { describe, expect, test } from "vitest";
import { stripEnvelopeFromMessage } from "./chat-sanitize.js";
describe("stripEnvelopeFromMessage", () => {
test("removes message_id hint lines from user messages", () => {
const input = {
role: "user",
content: "[WhatsApp 2026-01-24 13:36] yolo\n[message_id: 7b8b]",
};
const result = stripEnvelopeFromMessage(input) as { content?: string };
expect(result.content).toBe("yolo");
});
test("removes message_id hint lines from text content arrays", () => {
const input = {
role: "user",
content: [{ type: "text", text: "hi\n[message_id: abc123]" }],
};
const result = stripEnvelopeFromMessage(input) as {
content?: Array<{ type: string; text?: string }>;
};
expect(result.content?.[0]?.text).toBe("hi");
});
test("does not strip inline message_id text that is part of a line", () => {
const input = {
role: "user",
content: "I typed [message_id: 123] on purpose",
};
const result = stripEnvelopeFromMessage(input) as { content?: string };
expect(result.content).toBe("I typed [message_id: 123] on purpose");
});
test("does not strip assistant messages", () => {
const input = {
role: "assistant",
content: "note\n[message_id: 123]",
};
const result = stripEnvelopeFromMessage(input) as { content?: string };
expect(result.content).toBe("note\n[message_id: 123]");
});
});

View File

@@ -14,6 +14,8 @@ const ENVELOPE_CHANNELS = [
"BlueBubbles",
];
const MESSAGE_ID_LINE = /^\s*\[message_id:\s*[^\]]+\]\s*$/i;
function looksLikeEnvelopeHeader(header: string): boolean {
if (/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}Z\b/.test(header)) return true;
if (/\d{4}-\d{2}-\d{2} \d{2}:\d{2}\b/.test(header)) return true;
@@ -28,13 +30,20 @@ export function stripEnvelope(text: string): string {
return text.slice(match[0].length);
}
function stripMessageIdHints(text: string): string {
if (!text.includes("[message_id:")) return text;
const lines = text.split(/\r?\n/);
const filtered = lines.filter((line) => !MESSAGE_ID_LINE.test(line));
return filtered.length === lines.length ? text : filtered.join("\n");
}
function stripEnvelopeFromContent(content: unknown[]): { content: unknown[]; changed: boolean } {
let changed = false;
const next = content.map((item) => {
if (!item || typeof item !== "object") return item;
const entry = item as Record<string, unknown>;
if (entry.type !== "text" || typeof entry.text !== "string") return item;
const stripped = stripEnvelope(entry.text);
const stripped = stripMessageIdHints(stripEnvelope(entry.text));
if (stripped === entry.text) return item;
changed = true;
return {
@@ -55,7 +64,7 @@ export function stripEnvelopeFromMessage(message: unknown): unknown {
const next: Record<string, unknown> = { ...entry };
if (typeof entry.content === "string") {
const stripped = stripEnvelope(entry.content);
const stripped = stripMessageIdHints(stripEnvelope(entry.content));
if (stripped !== entry.content) {
next.content = stripped;
changed = true;
@@ -67,7 +76,7 @@ export function stripEnvelopeFromMessage(message: unknown): unknown {
changed = true;
}
} else if (typeof entry.text === "string") {
const stripped = stripEnvelope(entry.text);
const stripped = stripMessageIdHints(stripEnvelope(entry.text));
if (stripped !== entry.text) {
next.text = stripped;
changed = true;