UNPKG

@tencentdb-agent-memory/memory-tencentdb

Version:

Four-layer local memory system plugin for OpenClaw — auto-captures, structures, and profiles conversational knowledge using local LLM + SQLite vector search (L0→L1→L2→L3 pipeline)

89 lines (71 loc) 3.55 kB
/** * Text sanitization for L0 capture (client-side). * Mirrors the cleaning logic in extensions/memory-tencentdb/src/utils/sanitize.ts * — kept in sync to ensure the client and server filter the same noise. */ /** Strip injected memory tags + framework metadata blocks + media markers. */ export function sanitizeText(text: string): string { let cleaned = text; // Remove injected memory context tags (prevent feedback loops on re-capture) cleaned = cleaned.replace(/<relevant-memories>[\s\S]*?<\/relevant-memories>/g, ""); cleaned = cleaned.replace(/<user-persona>[\s\S]*?<\/user-persona>/g, ""); cleaned = cleaned.replace(/<relevant-scenes>[\s\S]*?<\/relevant-scenes>/g, ""); cleaned = cleaned.replace(/<scene-navigation>[\s\S]*?<\/scene-navigation>/g, ""); cleaned = cleaned.replace(/<memory-tools-guide>[\s\S]*?<\/memory-tools-guide>/g, ""); // Offload-injected task context blocks cleaned = cleaned.replace(/<current_task_context>[\s\S]*?<\/current_task_context>/g, ""); cleaned = cleaned.replace(/<history_task_context[\s\S]*?<\/history_task_context>/g, ""); // Framework-injected inbound metadata blocks (label + ```json ... ```) cleaned = cleaned.replace( /(?:Conversation info|Sender|Thread starter|Replied message|Forwarded message context|Chat history since last reply)\s*\(untrusted[\s\S]*?\):\s*```json\s*[\s\S]*?```/g, "", ); // Legacy conversation metadata JSON blocks cleaned = cleaned.replace(/```json\s*\{[\s\S]*?"session[\s\S]*?\}\s*```/g, ""); // Reply directive tags: [[reply_to_current]] cleaned = cleaned.replace(/\[\[reply_to[^\]]*\]\]\s*/g, ""); // Skill-selection wrappers: ¥¥[ ... ]¥¥ cleaned = cleaned.replace(/¥¥\[[\s\S]*?\]¥¥/g, ""); // Line-leading timestamps: [Tue 2026-03-24 03:48 UTC] / GMT+8 / GMT+5:30 cleaned = cleaned.replace(/^\[[\w\d\-:+ ]+\]\s*/gm, ""); // Gateway media-attachment markers cleaned = cleaned.replace(/\[media attached:[^\]]*\]\s*/g, ""); // Gateway image-reply instructions cleaned = cleaned.replace( /To send an image back,[\s\S]*?(?:Keep caption in the text body\.)\s*/g, "", ); // System exec blocks: "System: [timestamp] Exec completed ..." cleaned = cleaned.replace(/^System:\s*\[[\s\S]*?$/gm, ""); // Inline base64 image data URIs cleaned = cleaned.replace(/data:image\/[a-z+]+;base64,[A-Za-z0-9+/=]+/gi, ""); // Null chars + collapse whitespace cleaned = cleaned.replace(/\0/g, "").replace(/\n{3,}/g, "\n\n").trim(); return cleaned; } /** * Strip fenced code blocks from assistant replies before L0 capture. * Only applied to role=assistant — keeps explanatory text but drops noisy code. */ export function stripCodeBlocks(text: string): string { return text.replace(/```[^\n]*\n[\s\S]*?```/g, "").replace(/\n{3,}/g, "\n\n").trim(); } /** * L0 capture filter — permissive. Only drops messages that are structurally * useless (empty, framework bootstrap noise, slash commands). */ export function shouldCaptureL0(text: string): boolean { if (!text || !text.trim()) return false; if (isFrameworkNoise(text)) return false; if (text.startsWith("/")) return false; return true; } function isFrameworkNoise(text: string): boolean { const t = text.trim(); if (t === "(session bootstrap)") return true; if (t.startsWith("A new session was started via")) return true; if (/^✅\s*New session started/.test(t)) return true; if (t.startsWith("Pre-compaction memory flush")) return true; if (/^NO_REPLY\s*$/.test(t)) return true; return false; }