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
This commit is contained in:
Russell Ballestrini 2025-08-11 13:46:51 -04:00
parent 5d78911d5b
commit 4e122e708c
2 changed files with 22 additions and 7 deletions

15
app.py
View file

@ -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,
)

View file

@ -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