From 4e122e708c60c5710e8041e4b794d9c0ea12e571 Mon Sep 17 00:00:00 2001 From: Russell Ballestrini Date: Mon, 11 Aug 2025 13:46:51 -0400 Subject: [PATCH] Refactor streaming protocol to separate username/model from content Backend changes: - Send username, model_name, and is_first_chunk as separate fields - Keep actual content separate from header formatting - Cleaner separation of concerns in streaming protocol Frontend changes: - Build display content with header only for visual rendering - Keep messageBuffers clean (content only) for TTS processing - TTS now processes pure content without username headers This fixes the issue where TTS was reading 'fxhp (model):' prefix --- app.py | 15 ++++++++++++--- templates/chat.html | 14 ++++++++++---- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/app.py b/app.py index cdc223e..ac9582a 100644 --- a/app.py +++ b/app.py @@ -811,7 +811,10 @@ def chat_claude( "message_chunk", { "id": msg_id, - "content": f"**{username} ({model_name}):**\n\n{content}", + "content": content, + "username": username, + "model_name": model_name, + "is_first_chunk": True, }, room=room.name, ) @@ -969,7 +972,10 @@ def chat_gpt(username, room_name, model_name="gpt-4o-mini"): "message_chunk", { "id": msg_id, - "content": f"**{username} ({model_name}):**\n\n{content}", + "content": content, + "username": username, + "model_name": model_name, + "is_first_chunk": True, }, room=room.name, ) @@ -1083,7 +1089,10 @@ def chat_llama(username, room_name, model_name="mistral-7b-instruct-v0.2.Q3_K_L. "message_chunk", { "id": msg_id, - "content": f"**{username} ({model_name}):**\n\n{content}", + "content": content, + "username": username, + "model_name": model_name, + "is_first_chunk": True, }, room=room.name, ) diff --git a/templates/chat.html b/templates/chat.html index 29c82d5..2d4e57c 100644 --- a/templates/chat.html +++ b/templates/chat.html @@ -762,12 +762,18 @@ socket.on("message_chunk", (data) => { // Append the chunk to the buffer messageBuffers[data.id] += data.content; - - // Process the entire buffer with marked and set it as the content of the target element - const sanitizedContent = DOMPurify.sanitize(marked.marked(messageBuffers[data.id]), dompurify_config); + + // Build the content for display (includes header for first chunk) + let displayContent = messageBuffers[data.id]; + if (data.is_first_chunk && data.username && data.model_name) { + displayContent = `**${data.username} (${data.model_name}):**\n\n${displayContent}`; + } + + // Process the display content with marked and set it as the content of the target element + const sanitizedContent = DOMPurify.sanitize(marked.marked(displayContent), dompurify_config); targetMessageElement.innerHTML = sanitizedContent; - // Store the raw markdown in a data attribute for later use in editing + // Store the raw markdown in a data attribute for later use in editing (without header for clean editing) targetMessageElement.dataset.rawMarkdown = messageBuffers[data.id]; // Apply syntax highlighting to code blocks within the content