Files
Moltbot/src/shared/chat-envelope.ts
Vincent Koc 35be87b09b fix(tui): strip inbound metadata blocks from user messages (clean rewrite) (#22345)
* fix(tui): strip inbound metadata blocks from user text

* chore: clean up metadata-strip format and changelog credit

* chore: format tui metadata-strip tests

* test: align metadata-strip regression expectations

* refactor: reuse canonical inbound metadata stripper

* test: allow tmp media fixture paths in media-understanding tests

* refactor: reuse canonical inbound metadata stripper

* format: fix changelog blank line after headings

* test: fix unrelated check typing regressions

* test: align memory async mock embedding signatures

* test: avoid tsgo mock typing pitfall

* test: restore async search mock typings in merge tree

* test: trigger ci rerun without behavior change

* chore: dedupe todays changelog entries

* fix: dedupe sqlite mock keys in qmd manager test

* Update qmd-manager.test.ts

* test: align chat metadata sanitization expectation
2026-02-20 23:52:43 -05:00

49 lines
1.2 KiB
TypeScript

const ENVELOPE_PREFIX = /^\[([^\]]+)\]\s*/;
const ENVELOPE_CHANNELS = [
"WebChat",
"WhatsApp",
"Telegram",
"Signal",
"Slack",
"Discord",
"Google Chat",
"iMessage",
"Teams",
"Matrix",
"Zalo",
"Zalo Personal",
"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;
}
return ENVELOPE_CHANNELS.some((label) => header.startsWith(`${label} `));
}
export function stripEnvelope(text: string): string {
const match = text.match(ENVELOPE_PREFIX);
if (!match) {
return text;
}
const header = match[1] ?? "";
if (!looksLikeEnvelopeHeader(header)) {
return text;
}
return text.slice(match[0].length);
}
export 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");
}