fix: hide message_id hints in web chat
This commit is contained in:
42
src/gateway/chat-sanitize.test.ts
Normal file
42
src/gateway/chat-sanitize.test.ts
Normal 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]");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -14,6 +14,8 @@ const ENVELOPE_CHANNELS = [
|
|||||||
"BlueBubbles",
|
"BlueBubbles",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const MESSAGE_ID_LINE = /^\s*\[message_id:\s*[^\]]+\]\s*$/i;
|
||||||
|
|
||||||
function looksLikeEnvelopeHeader(header: string): boolean {
|
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}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;
|
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);
|
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 } {
|
function stripEnvelopeFromContent(content: unknown[]): { content: unknown[]; changed: boolean } {
|
||||||
let changed = false;
|
let changed = false;
|
||||||
const next = content.map((item) => {
|
const next = content.map((item) => {
|
||||||
if (!item || typeof item !== "object") return item;
|
if (!item || typeof item !== "object") return item;
|
||||||
const entry = item as Record<string, unknown>;
|
const entry = item as Record<string, unknown>;
|
||||||
if (entry.type !== "text" || typeof entry.text !== "string") return item;
|
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;
|
if (stripped === entry.text) return item;
|
||||||
changed = true;
|
changed = true;
|
||||||
return {
|
return {
|
||||||
@@ -55,7 +64,7 @@ export function stripEnvelopeFromMessage(message: unknown): unknown {
|
|||||||
const next: Record<string, unknown> = { ...entry };
|
const next: Record<string, unknown> = { ...entry };
|
||||||
|
|
||||||
if (typeof entry.content === "string") {
|
if (typeof entry.content === "string") {
|
||||||
const stripped = stripEnvelope(entry.content);
|
const stripped = stripMessageIdHints(stripEnvelope(entry.content));
|
||||||
if (stripped !== entry.content) {
|
if (stripped !== entry.content) {
|
||||||
next.content = stripped;
|
next.content = stripped;
|
||||||
changed = true;
|
changed = true;
|
||||||
@@ -67,7 +76,7 @@ export function stripEnvelopeFromMessage(message: unknown): unknown {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
} else if (typeof entry.text === "string") {
|
} else if (typeof entry.text === "string") {
|
||||||
const stripped = stripEnvelope(entry.text);
|
const stripped = stripMessageIdHints(stripEnvelope(entry.text));
|
||||||
if (stripped !== entry.text) {
|
if (stripped !== entry.text) {
|
||||||
next.text = stripped;
|
next.text = stripped;
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user