From 708e59e6c93cbebfb2e601c66e591ccdd41999b0 Mon Sep 17 00:00:00 2001
From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com>
Date: Thu, 12 Jun 2025 08:37:40 +0000
Subject: [PATCH 1/2] feat: filter thinking tags from copied assistant
responses
- Added stripThinkingTags utility function to remove ... tags
- Updated SystemMessage copy functionality to use filtered content
- Handles both complete and incomplete thinking tags
- Cleans up extra whitespace after tag removal
Fixes #118
Co-authored-by: AnthonyRonning
---
frontend/src/components/markdown.tsx | 16 ++++++++++++++++
frontend/src/routes/_auth.chat.$chatId.tsx | 5 +++--
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/frontend/src/components/markdown.tsx b/frontend/src/components/markdown.tsx
index 67058d6b..af3e92b6 100644
--- a/frontend/src/components/markdown.tsx
+++ b/frontend/src/components/markdown.tsx
@@ -176,6 +176,22 @@ function parseThinkingTags(content: string, isComplete: boolean = false): Parsed
return parts;
}
+export function stripThinkingTags(content: string): string {
+ // Handle the edge case: followed by only whitespace and no closing tag
+ if (/^\s*$/m.test(content) && !content.includes("")) {
+ return content.replace(/^\s*/m, "");
+ }
+
+ // Pattern to match tags (complete or incomplete) and remove them entirely
+ const thinkPattern = /([\s\S]*?)<\/think>|([\s\S]*?)$/g;
+
+ // Replace all thinking tags with empty string and clean up extra whitespace
+ return content
+ .replace(thinkPattern, "")
+ .replace(/\n\s*\n\s*\n/g, "\n\n") // Replace multiple consecutive newlines with double newlines
+ .trim();
+}
+
export function PreCode(props: JSX.IntrinsicElements["pre"]) {
const ref = useRef(null);
diff --git a/frontend/src/routes/_auth.chat.$chatId.tsx b/frontend/src/routes/_auth.chat.$chatId.tsx
index 115363fc..c3079900 100644
--- a/frontend/src/routes/_auth.chat.$chatId.tsx
+++ b/frontend/src/routes/_auth.chat.$chatId.tsx
@@ -4,7 +4,7 @@ import { AsteriskIcon, Check, Copy, UserIcon, ChevronDown, SquarePenIcon } from
import ChatBox from "@/components/ChatBox";
import { useOpenAI } from "@/ai/useOpenAi";
import { useLocalState } from "@/state/useLocalState";
-import { Markdown } from "@/components/markdown";
+import { Markdown, stripThinkingTags } from "@/components/markdown";
import { ChatMessage, Chat, DEFAULT_MODEL_ID } from "@/state/LocalStateContext";
import { AlertDestructive } from "@/components/AlertDestructive";
import { Sidebar, SidebarToggle } from "@/components/Sidebar";
@@ -46,7 +46,8 @@ function SystemMessage({
const handleCopy = useCallback(async () => {
try {
- await navigator.clipboard.writeText(text);
+ const textWithoutThinking = stripThinkingTags(text);
+ await navigator.clipboard.writeText(textWithoutThinking);
setIsCopied(true);
setTimeout(() => setIsCopied(false), 2000);
} catch (error) {
From 8a59d2bef3f961bb931c34986c4a298a6fe24b87 Mon Sep 17 00:00:00 2001
From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com>
Date: Thu, 12 Jun 2025 15:34:14 +0000
Subject: [PATCH 2/2] refactor: eliminate duplicate logic in stripThinkingTags
- Refactor stripThinkingTags to reuse parseThinkingTags logic
- Remove duplicate regex patterns and edge case handling
- Improve newline normalization with better regex pattern
- Addresses code review feedback about DRY violations
Co-authored-by: AnthonyRonning
---
frontend/src/components/markdown.tsx | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/frontend/src/components/markdown.tsx b/frontend/src/components/markdown.tsx
index af3e92b6..f7924e89 100644
--- a/frontend/src/components/markdown.tsx
+++ b/frontend/src/components/markdown.tsx
@@ -177,19 +177,15 @@ function parseThinkingTags(content: string, isComplete: boolean = false): Parsed
}
export function stripThinkingTags(content: string): string {
- // Handle the edge case: followed by only whitespace and no closing tag
- if (/^\s*$/m.test(content) && !content.includes("")) {
- return content.replace(/^\s*/m, "");
- }
-
- // Pattern to match tags (complete or incomplete) and remove them entirely
- const thinkPattern = /([\s\S]*?)<\/think>|([\s\S]*?)$/g;
-
- // Replace all thinking tags with empty string and clean up extra whitespace
- return content
- .replace(thinkPattern, "")
- .replace(/\n\s*\n\s*\n/g, "\n\n") // Replace multiple consecutive newlines with double newlines
- .trim();
+ return (
+ parseThinkingTags(content, true) // leverage single source of truth
+ .filter((p) => p.type === "content")
+ .map((p) => p.content)
+ .join("")
+ // collapse ≥3 consecutive blank lines to two
+ .replace(/\n{3,}/g, "\n\n")
+ .trim()
+ );
}
export function PreCode(props: JSX.IntrinsicElements["pre"]) {