Spaces:
Running
Running
import React from 'react'; | |
import { ChatHistoryProps } from '@/lib/types'; | |
import TypingIndicator from './TypingIndicator'; | |
import { useScrollToBottom } from '@/lib/hooks'; | |
import { AlertTriangle } from 'lucide-react'; | |
const ChatHistory: React.FC<ChatHistoryProps> = ({ | |
messages, | |
isLoading, | |
currentModel = 'openai' | |
}) => { | |
const scrollRef = useScrollToBottom([messages, isLoading]); | |
// Check if we're in fallback mode by looking at the model or fallback indicator in messages | |
const isFallbackMode = currentModel === 'qwen' || | |
messages.some(message => | |
message.role === 'assistant' && | |
message.content.includes('fallback mode') | |
); | |
return ( | |
<div | |
ref={scrollRef} | |
className="chat-container overflow-y-auto pb-4 px-2" | |
style={{ height: 'calc(100vh - 180px)' }} | |
> | |
{/* Fallback mode indicator */} | |
{isFallbackMode && ( | |
<div className="bg-amber-50 border-l-4 border-amber-400 p-4 mb-4 rounded-md"> | |
<div className="flex items-center"> | |
<div className="flex-shrink-0"> | |
<AlertTriangle className="h-5 w-5 text-amber-400" /> | |
</div> | |
<div className="ml-3"> | |
<p className="text-sm text-amber-700"> | |
<strong>Qwen Fallback Mode Active:</strong> The OpenAI API is currently unavailable. | |
Responses are being generated by the Qwen model instead. | |
</p> | |
</div> | |
</div> | |
</div> | |
)} | |
{messages.map((message, index) => { | |
// Check if this is a fallback message directly from the content | |
const isMessageFallback = message.role === 'assistant' && | |
(message.content.includes('fallback mode') || | |
message.content.includes('Qwen model')); | |
// Determine if this message appears to be a fallback response | |
const isAssistantFallbackMessage = message.role === 'assistant' && | |
(currentModel === 'qwen' || isMessageFallback); | |
// Clean up fallback message for display | |
let displayContent = isAssistantFallbackMessage | |
? message.content.replace(/\n\n\(Note: I'm currently operating in fallback mode.*\)$/, '') | |
: message.content; | |
// Remove any thinking process sections for Qwen responses | |
if (isAssistantFallbackMessage) { | |
// Remove <think> tags and their content | |
displayContent = displayContent.replace(/<think>[\s\S]*?<\/think>/g, ''); | |
// Remove any other XML-like tags | |
displayContent = displayContent.replace(/<[^>]*>/g, ''); | |
// Clean up any excessive whitespace | |
displayContent = displayContent.replace(/^\s+|\s+$/g, ''); | |
displayContent = displayContent.replace(/\n{3,}/g, '\n\n'); | |
} | |
return ( | |
<div | |
key={index} | |
className={`flex items-start ${message.role === 'user' ? 'justify-end' : ''} mb-4`} | |
> | |
{message.role !== 'user' && ( | |
<div className="flex-shrink-0 mr-3"> | |
<div className={`h-8 w-8 rounded-full ${ | |
isAssistantFallbackMessage ? 'bg-amber-500' : 'bg-primary' | |
} flex items-center justify-center text-white`}> | |
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> | |
<path d="M2 5a2 2 0 012-2h7a2 2 0 012 2v4a2 2 0 01-2 2H9l-3 3v-3H4a2 2 0 01-2-2V5z" /> | |
<path d="M15 7v2a4 4 0 01-4 4H9.828l-1.766 1.767c.28.149.599.233.938.233h2l3 3v-3h2a2 2 0 002-2V9a2 2 0 00-2-2h-1z" /> | |
</svg> | |
</div> | |
</div> | |
)} | |
<div | |
className={`${ | |
message.role === 'user' | |
? 'bg-primary text-white' | |
: isAssistantFallbackMessage | |
? 'bg-amber-50 border border-amber-200 text-gray-800' | |
: 'bg-white text-gray-800' | |
} rounded-lg p-4 shadow-sm max-w-[85%]`} | |
> | |
<p className="whitespace-pre-wrap">{displayContent}</p> | |
{isAssistantFallbackMessage && isMessageFallback && ( | |
<p className="mt-2 text-xs text-amber-600 italic"> | |
(This response was generated using the Qwen fallback model) | |
</p> | |
)} | |
</div> | |
{message.role === 'user' && ( | |
<div className="flex-shrink-0 ml-3"> | |
<div className="h-8 w-8 rounded-full bg-gray-300 flex items-center justify-center text-gray-600"> | |
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"> | |
<path fillRule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clipRule="evenodd" /> | |
</svg> | |
</div> | |
</div> | |
)} | |
</div> | |
); | |
})} | |
<TypingIndicator isVisible={isLoading} /> | |
</div> | |
); | |
}; | |
export default ChatHistory; | |