diff --git a/frontend/src/components/ChatInterface.tsx b/frontend/src/components/ChatInterface.tsx index 2cb0a22..eb33eed 100644 --- a/frontend/src/components/ChatInterface.tsx +++ b/frontend/src/components/ChatInterface.tsx @@ -68,18 +68,10 @@ const ChatInterface: React.FC = () => { const cleanMarkdown = (text: string): string => { return text - // Collapse all 2+ blank lines into single blank line everywhere - .replace(/\n{3,}/g, '\n\n') - // Remove blank line between heading and any content - .replace(/(^#{1,6}\s+.+)\n\n(?=\S)/gm, '$1\n') - // Remove blank line between bold header (**Text:**) and next line - .replace(/(\*\*[^*]+\*\*:?[^\n]*)\n\n(?=\S)/gm, '$1\n') - // Remove blank line before list items (after any text) - .replace(/([^\n])\n\n(?=\d+[\.\)]\s)/g, '$1\n') - .replace(/([^\n])\n\n(?=[-*]\s)/g, '$1\n') - // Remove blank lines between list items - .replace(/([-*]\s+[^\n]+)\n\n(?=[-*]\s)/g, '$1\n') - .replace(/(\d+[\.\)]\s+[^\n]+)\n\n(?=\d+[\.\)]\s)/g, '$1\n'); + // Nuclear: collapse ALL double+ newlines to single newline + .replace(/\n{2,}/g, '\n') + // Add back paragraph break ONLY before bold section headers (**Text:**) + .replace(/\n(\*\*[^*]+\*\*)/g, '\n\n$1'); }; const handleSend = async () => { diff --git a/frontend/src/context/ChatContext.tsx b/frontend/src/context/ChatContext.tsx index 12eec4a..bdc4274 100644 --- a/frontend/src/context/ChatContext.tsx +++ b/frontend/src/context/ChatContext.tsx @@ -141,11 +141,32 @@ export const ChatProvider: React.FC<{ children: ReactNode }> = ({ children }) => }, ]); - // Update conversation in list (move to top) - setConversations((prev) => { - const updated = prev.filter((c) => c.id !== currentConversation.id); - return [currentConversation, ...updated]; - }); + // Auto-rename conversation on first message + if (currentConversation.title === 'New Conversation' && messages.length === 0) { + const autoTitle = content.length > 50 + ? content.substring(0, 50).trim() + '...' + : content; + try { + await conversationAPI.update(currentConversation.id, autoTitle); + setCurrentConversation((prev) => prev ? { ...prev, title: autoTitle } : null); + setConversations((prev) => { + const updated = prev.filter((c) => c.id !== currentConversation.id); + return [{ ...currentConversation, title: autoTitle }, ...updated]; + }); + } catch { + // Rename failed — not critical, keep default title + setConversations((prev) => { + const updated = prev.filter((c) => c.id !== currentConversation.id); + return [currentConversation, ...updated]; + }); + } + } else { + // Update conversation in list (move to top) + setConversations((prev) => { + const updated = prev.filter((c) => c.id !== currentConversation.id); + return [currentConversation, ...updated]; + }); + } } catch (err: any) { console.error('Failed to send message:', err); setError(err.response?.data?.detail || 'Failed to send message');