fix: strip envelopes in chat history

This commit is contained in:
Peter Steinberger
2026-01-19 22:48:47 +00:00
parent 4bac76e66d
commit 44c61a77c5
4 changed files with 136 additions and 1 deletions

View File

@@ -0,0 +1,89 @@
const ENVELOPE_PREFIX = /^\[([^\]]+)\]\s*/;
const ENVELOPE_CHANNELS = [
"WebChat",
"WhatsApp",
"Telegram",
"Signal",
"Slack",
"Discord",
"iMessage",
"Teams",
"Matrix",
"Zalo",
"Zalo Personal",
"BlueBubbles",
];
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);
}
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);
if (stripped === entry.text) return item;
changed = true;
return {
...entry,
text: stripped,
};
});
return { content: next, changed };
}
export function stripEnvelopeFromMessage(message: unknown): unknown {
if (!message || typeof message !== "object") return message;
const entry = message as Record<string, unknown>;
const role = typeof entry.role === "string" ? entry.role.toLowerCase() : "";
if (role !== "user") return message;
let changed = false;
const next: Record<string, unknown> = { ...entry };
if (typeof entry.content === "string") {
const stripped = stripEnvelope(entry.content);
if (stripped !== entry.content) {
next.content = stripped;
changed = true;
}
} else if (Array.isArray(entry.content)) {
const updated = stripEnvelopeFromContent(entry.content);
if (updated.changed) {
next.content = updated.content;
changed = true;
}
} else if (typeof entry.text === "string") {
const stripped = stripEnvelope(entry.text);
if (stripped !== entry.text) {
next.text = stripped;
changed = true;
}
}
return changed ? next : message;
}
export function stripEnvelopeFromMessages(messages: unknown[]): unknown[] {
if (messages.length === 0) return messages;
let changed = false;
const next = messages.map((message) => {
const stripped = stripEnvelopeFromMessage(message);
if (stripped !== message) changed = true;
return stripped;
});
return changed ? next : messages;
}