diff --git a/web-app/src/containers/ThinkingBlock.tsx b/web-app/src/containers/ThinkingBlock.tsx index c4e6742c5..7a1e7b540 100644 --- a/web-app/src/containers/ThinkingBlock.tsx +++ b/web-app/src/containers/ThinkingBlock.tsx @@ -30,14 +30,31 @@ const ThinkingBlock = ({ id, text }: Props) => { const { thinkingState, setThinkingState } = useThinkingStore() const { streamingContent } = useAppState() const { t } = useTranslation() - const loading = !text.includes('') && streamingContent + // Check for thinking formats + const hasThinkTag = text.includes('') && !text.includes('') + const hasAnalysisChannel = text.includes('<|channel|>analysis<|message|>') && !text.includes('<|start|>assistant<|channel|>final<|message|>') + const loading = (hasThinkTag || hasAnalysisChannel) && streamingContent const isExpanded = thinkingState[id] ?? (loading ? true : false) const handleClick = () => { const newExpandedState = !isExpanded setThinkingState(id, newExpandedState) } - if (!text.replace(/<\/?think>/g, '').trim()) return null + // Extract thinking content from either format + const extractThinkingContent = (text: string) => { + return text + .replace(/<\/?think>/g, '') + .replace(/<\|channel\|>analysis<\|message\|>/g, '') + .replace(/<\|start\|>assistant<\|channel\|>final<\|message\|>/g, '') + .replace(/assistant<\|channel\|>final<\|message\|>/g, '') + .replace(/<\|channel\|>/g, '') // remove any remaining channel markers + .replace(/<\|message\|>/g, '') // remove any remaining message markers + .replace(/<\|start\|>/g, '') // remove any remaining start markers + .trim() + } + + const thinkingContent = extractThinkingContent(text) + if (!thinkingContent) return null return (
{ {isExpanded && (
- /g, '').trim()} /> +
)}
diff --git a/web-app/src/containers/ThreadContent.tsx b/web-app/src/containers/ThreadContent.tsx index 716c6bfc4..54ba342cb 100644 --- a/web-app/src/containers/ThreadContent.tsx +++ b/web-app/src/containers/ThreadContent.tsx @@ -170,18 +170,33 @@ export const ThreadContent = memo( ) const { reasoningSegment, textSegment } = useMemo(() => { - const isThinking = text.includes('') && !text.includes('') - if (isThinking) return { reasoningSegment: text, textSegment: '' } + // Check for thinking formats + const hasThinkTag = text.includes('') && !text.includes('') + const hasAnalysisChannel = text.includes('<|channel|>analysis<|message|>') && !text.includes('<|start|>assistant<|channel|>final<|message|>') + + if (hasThinkTag || hasAnalysisChannel) return { reasoningSegment: text, textSegment: '' } - const match = text.match(/([\s\S]*?)<\/think>/) - if (match?.index === undefined) - return { reasoningSegment: undefined, textSegment: text } - - const splitIndex = match.index + match[0].length - return { - reasoningSegment: text.slice(0, splitIndex), - textSegment: text.slice(splitIndex), + // Check for completed think tag format + const thinkMatch = text.match(/([\s\S]*?)<\/think>/) + if (thinkMatch?.index !== undefined) { + const splitIndex = thinkMatch.index + thinkMatch[0].length + return { + reasoningSegment: text.slice(0, splitIndex), + textSegment: text.slice(splitIndex), + } } + + // Check for completed analysis channel format + const analysisMatch = text.match(/<\|channel\|>analysis<\|message\|>([\s\S]*?)<\|start\|>assistant<\|channel\|>final<\|message\|>/) + if (analysisMatch?.index !== undefined) { + const splitIndex = analysisMatch.index + analysisMatch[0].length + return { + reasoningSegment: text.slice(0, splitIndex), + textSegment: text.slice(splitIndex), + } + } + + return { reasoningSegment: undefined, textSegment: text } }, [text]) const { getMessages, deleteMessage } = useMessages()