diff --git a/ui/src/ui/format.test.ts b/ui/src/ui/format.test.ts
index d7acecebb..2a687c099 100644
--- a/ui/src/ui/format.test.ts
+++ b/ui/src/ui/format.test.ts
@@ -21,6 +21,7 @@ describe("stripThinkingTags", () => {
it("returns original text when no tags exist", () => {
expect(stripThinkingTags("Hello")).toBe("Hello");
});
+<<<<<<< fix/tui-final-tag-strip
it("strips … segments", () => {
const input = "\n\nHello there\n\n";
@@ -39,4 +40,27 @@ describe("stripThinkingTags", () => {
expect(stripThinkingTags("Hello")).toBe("Hello");
});
});
+||||||| temp/landpr-
+});
+=======
+>>>>>>> local
+ it("strips … segments while keeping content", () => {
+ const input = "\n\nHello there\n\n";
+ expect(stripThinkingTags(input)).toBe("Hello there\n\n");
+ });
+
+ it("strips mixed and tags", () => {
+ const input = "reasoning\n\nHello";
+ expect(stripThinkingTags(input)).toBe("Hello");
+ });
+
+ it("strips unpaired tags", () => {
+ expect(stripThinkingTags("Hello")).toBe("Hello");
+ expect(stripThinkingTags("Hello")).toBe("Hello");
+ });
+
+ it("keeps incomplete {
+ expect(stripThinkingTags(" v.length > 0);
}
+<<<<<<< fix/tui-final-tag-strip
const THINKING_TAG_RE = /<\s*\/?\s*(?:think(?:ing)?|final)\s*>/gi;
const THINKING_OPEN_RE = /<\s*(?:think(?:ing)?|final)\s*>/i;
const THINKING_CLOSE_RE = /<\s*\/\s*(?:think(?:ing)?|final)\s*>/i;
+||||||| temp/landpr-
+const THINKING_TAG_RE = /<\s*\/?\s*think(?:ing)?\s*>/gi;
+const THINKING_OPEN_RE = /<\s*think(?:ing)?\s*>/i;
+const THINKING_CLOSE_RE = /<\s*\/\s*think(?:ing)?\s*>/i;
+=======
+const FINAL_TAG_RE = /<\s*\/?\s*final\s*>/gi;
+const THINKING_TAG_RE = /<\s*\/?\s*think(?:ing)?\s*>/gi;
+const THINKING_OPEN_RE = /<\s*think(?:ing)?\s*>/i;
+const THINKING_CLOSE_RE = /<\s*\/\s*think(?:ing)?\s*>/i;
+>>>>>>> local
export function stripThinkingTags(value: string): string {
if (!value) return value;
- const hasOpen = THINKING_OPEN_RE.test(value);
- const hasClose = THINKING_CLOSE_RE.test(value);
- if (!hasOpen && !hasClose) return value;
- // If we don't have a balanced pair, avoid dropping trailing content.
- if (hasOpen !== hasClose) {
- if (!hasOpen) return value.replace(THINKING_CLOSE_RE, "").trimStart();
- return value.replace(THINKING_OPEN_RE, "").trimStart();
+ let cleaned = value;
+ let strippedFinal = false;
+ if (FINAL_TAG_RE.test(cleaned)) {
+ FINAL_TAG_RE.lastIndex = 0;
+ cleaned = cleaned.replace(FINAL_TAG_RE, "");
+ strippedFinal = true;
+ } else {
+ FINAL_TAG_RE.lastIndex = 0;
}
- if (!THINKING_TAG_RE.test(value)) return value;
+ const hasOpen = THINKING_OPEN_RE.test(cleaned);
+ const hasClose = THINKING_CLOSE_RE.test(cleaned);
+ if (!hasOpen && !hasClose) return strippedFinal ? cleaned.trimStart() : cleaned;
+ // If we don't have a balanced pair, avoid dropping trailing content.
+ if (hasOpen !== hasClose) {
+ if (!hasOpen) return cleaned.replace(THINKING_CLOSE_RE, "").trimStart();
+ return cleaned.replace(THINKING_OPEN_RE, "").trimStart();
+ }
+
+ if (!THINKING_TAG_RE.test(cleaned)) {
+ THINKING_TAG_RE.lastIndex = 0;
+ return strippedFinal ? cleaned.trimStart() : cleaned;
+ }
THINKING_TAG_RE.lastIndex = 0;
let result = "";
let lastIndex = 0;
let inThinking = false;
- for (const match of value.matchAll(THINKING_TAG_RE)) {
+ for (const match of cleaned.matchAll(THINKING_TAG_RE)) {
const idx = match.index ?? 0;
if (!inThinking) {
- result += value.slice(lastIndex, idx);
+ result += cleaned.slice(lastIndex, idx);
}
const tag = match[0].toLowerCase();
inThinking = !tag.includes("/");
lastIndex = idx + match[0].length;
}
if (!inThinking) {
- result += value.slice(lastIndex);
+ result += cleaned.slice(lastIndex);
}
return result.trimStart();
}