diff --git a/frontend/src/components/markdown.tsx b/frontend/src/components/markdown.tsx index 67058d6be..f7924e899 100644 --- a/frontend/src/components/markdown.tsx +++ b/frontend/src/components/markdown.tsx @@ -176,6 +176,18 @@ function parseThinkingTags(content: string, isComplete: boolean = false): Parsed return parts; } +export function stripThinkingTags(content: string): string { + 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"]) { const ref = useRef(null); diff --git a/frontend/src/routes/_auth.chat.$chatId.tsx b/frontend/src/routes/_auth.chat.$chatId.tsx index 115363fc7..c30799001 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) {