Web UI: strip relevant-memories scaffolding

This commit is contained in:
Vignesh Natarajan
2026-02-28 13:20:50 -08:00
parent ea4f5106ea
commit e90429794a
6 changed files with 148 additions and 2 deletions

View File

@@ -0,0 +1,49 @@
import { describe, expect, it } from "vitest";
import { stripAssistantInternalScaffolding } from "./assistant-visible-text.js";
describe("stripAssistantInternalScaffolding", () => {
it("strips reasoning tags", () => {
const input = ["<thinking>", "secret", "</thinking>", "Visible"].join("\n");
expect(stripAssistantInternalScaffolding(input)).toBe("Visible");
});
it("strips relevant-memories scaffolding blocks", () => {
const input = [
"<relevant-memories>",
"The following memories may be relevant to this conversation:",
"- Internal memory note",
"</relevant-memories>",
"",
"User-visible answer",
].join("\n");
expect(stripAssistantInternalScaffolding(input)).toBe("User-visible answer");
});
it("supports relevant_memories tag variants", () => {
const input = [
"<relevant_memories>",
"Internal memory note",
"</relevant_memories>",
"Visible",
].join("\n");
expect(stripAssistantInternalScaffolding(input)).toBe("Visible");
});
it("keeps relevant-memories tags inside fenced code", () => {
const input = [
"```xml",
"<relevant-memories>",
"sample",
"</relevant-memories>",
"```",
"",
"Visible text",
].join("\n");
expect(stripAssistantInternalScaffolding(input)).toBe(input);
});
it("hides unfinished relevant-memories blocks", () => {
const input = ["Hello", "<relevant-memories>", "internal-only"].join("\n");
expect(stripAssistantInternalScaffolding(input)).toBe("Hello\n");
});
});

View File

@@ -0,0 +1,47 @@
import { findCodeRegions, isInsideCode } from "./code-regions.js";
import { stripReasoningTagsFromText } from "./reasoning-tags.js";
const MEMORY_TAG_RE = /<\s*(\/?)\s*relevant[-_]memories\b[^<>]*>/gi;
const MEMORY_TAG_QUICK_RE = /<\s*\/?\s*relevant[-_]memories\b/i;
function stripRelevantMemoriesTags(text: string): string {
if (!text || !MEMORY_TAG_QUICK_RE.test(text)) {
return text;
}
MEMORY_TAG_RE.lastIndex = 0;
const codeRegions = findCodeRegions(text);
let result = "";
let lastIndex = 0;
let inMemoryBlock = false;
for (const match of text.matchAll(MEMORY_TAG_RE)) {
const idx = match.index ?? 0;
if (isInsideCode(idx, codeRegions)) {
continue;
}
const isClose = match[1] === "/";
if (!inMemoryBlock) {
result += text.slice(lastIndex, idx);
if (!isClose) {
inMemoryBlock = true;
}
} else if (isClose) {
inMemoryBlock = false;
}
lastIndex = idx + match[0].length;
}
if (!inMemoryBlock) {
result += text.slice(lastIndex);
}
return result;
}
export function stripAssistantInternalScaffolding(text: string): string {
const withoutReasoning = stripReasoningTagsFromText(text, { mode: "preserve", trim: "start" });
return stripRelevantMemoriesTags(withoutReasoning).trimStart();
}