Refactor LLM parsing and overhaul connection UI

- Strip content up to the “final<|message|>” token in OpenAI responses.
- Replace the text‑based connection‑status indicator with a small
  flashing circle.
- Simplify updateConnectionStatus to take only the status argument.
- Remove special handling of the initial assistant message and
  streamline empty‑state removal.
- Clean up stray blank lines in the announcement template.
This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-10-15 22:24:04 -03:00
parent ff89298e61
commit 648e7f48f9
3 changed files with 81 additions and 74 deletions

View file

@ -68,10 +68,18 @@ impl LLMProvider for OpenAIClient {
.await?; .await?;
let result: Value = response.json().await?; let result: Value = response.json().await?;
let content = result["choices"][0]["message"]["content"] let raw_content = result["choices"][0]["message"]["content"]
.as_str() .as_str()
.unwrap_or("") .unwrap_or("");
.to_string(); // Define the end token we want to skip up to. Adjust the token string if needed.
let end_token = "final<|message|>";
let content = if let Some(pos) = raw_content.find(end_token) {
// Skip everything up to and including the end token.
raw_content[(pos + end_token.len())..].to_string()
} else {
// If the token is not found, return the full content.
raw_content.to_string()
};
Ok(content) Ok(content)
} }

View file

@ -3,7 +3,5 @@ TALK "Olá, pode me perguntar sobre qualquer coisa..."
let text = GET "default.gbdrive/default.pdf" let text = GET "default.gbdrive/default.pdf"
let resume = LLM "Say Hello and present a a resume from " + text let resume = LLM "Say Hello and present a a resume from " + text
TALK resume TALK resume
SET_CONTEXT "Este é o documento que você deve usar para responder dúvidas: " + text SET_CONTEXT "Este é o documento que você deve usar para responder dúvidas: " + text
return true; return true;

View file

@ -436,34 +436,57 @@
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
} }
/* Updated Connection Status - Small Flashing Circle */
.connection-status { .connection-status {
position: fixed; position: fixed;
top: 10px; top: 15px;
right: 10px; right: 15px;
padding: 8px 12px; width: 16px;
border-radius: 20px; height: 16px;
font-size: 12px; border-radius: 50%;
font-weight: 600;
z-index: 1000; z-index: 1000;
transition: all 0.3s ease; transition: all 0.3s ease;
} box-shadow: 0 0 10px currentColor;
.connection-status.connected {
background: rgba(100, 255, 100, 0.2);
border: 1px solid rgba(100, 255, 100, 0.4);
color: #90ff90;
}
.connection-status.disconnected {
background: rgba(255, 100, 100, 0.2);
border: 1px solid rgba(255, 100, 100, 0.4);
color: #ff9090;
} }
.connection-status.connecting { .connection-status.connecting {
background: rgba(255, 215, 0, 0.2); background-color: #ffd700;
border: 1px solid rgba(255, 215, 0, 0.4); animation: connectingPulse 1.5s infinite;
color: #ffd700; }
.connection-status.connected {
background-color: #90ee90;
animation: connectedPulse 2s infinite;
}
.connection-status.disconnected {
background-color: #ff6b6b;
animation: none;
}
@keyframes connectingPulse {
0%,
100% {
opacity: 0.6;
transform: scale(0.8);
}
50% {
opacity: 1;
transform: scale(1);
}
}
@keyframes connectedPulse {
0%,
100% {
opacity: 0.8;
transform: scale(1);
}
50% {
opacity: 1;
transform: scale(1.1);
box-shadow: 0 0 15px #90ee90;
}
} }
/* Markdown Styles */ /* Markdown Styles */
@ -648,10 +671,10 @@
} }
.connection-status { .connection-status {
top: 5px; top: 10px;
right: 5px; right: 10px;
font-size: 10px; width: 14px;
padding: 6px 10px; height: 14px;
} }
} }
@ -688,9 +711,7 @@
</style> </style>
</head> </head>
<body> <body>
<div class="connection-status connecting" id="connectionStatus"> <div class="connection-status connecting" id="connectionStatus"></div>
🔄 Conectando...
</div>
<button class="sidebar-toggle" onclick="toggleSidebar()"></button> <button class="sidebar-toggle" onclick="toggleSidebar()"></button>
@ -777,9 +798,8 @@
document.getElementById("sidebar").classList.toggle("open"); document.getElementById("sidebar").classList.toggle("open");
} }
function updateConnectionStatus(status, message) { function updateConnectionStatus(status) {
connectionStatus.className = `connection-status ${status}`; connectionStatus.className = `connection-status ${status}`;
connectionStatus.textContent = message;
} }
function getWebSocketUrl() { function getWebSocketUrl() {
@ -810,7 +830,7 @@
async function initializeAuth() { async function initializeAuth() {
try { try {
updateConnectionStatus("connecting", "🔄 Conectando..."); updateConnectionStatus("connecting");
const response = await fetch("/api/auth"); const response = await fetch("/api/auth");
const authData = await response.json(); const authData = await response.json();
currentUserId = authData.user_id; currentUserId = authData.user_id;
@ -820,10 +840,7 @@
await triggerStartScript(); await triggerStartScript();
} catch (error) { } catch (error) {
console.error("Failed to initialize auth:", error); console.error("Failed to initialize auth:", error);
updateConnectionStatus( updateConnectionStatus("disconnected");
"disconnected",
"❌ Erro de conexão",
);
setTimeout(initializeAuth, 3000); setTimeout(initializeAuth, 3000);
} }
} }
@ -953,7 +970,7 @@
ws.onopen = function () { ws.onopen = function () {
console.log("Connected to WebSocket"); console.log("Connected to WebSocket");
updateConnectionStatus("connected", "✅ Conectado"); updateConnectionStatus("connected");
reconnectAttempts = 0; reconnectAttempts = 0;
// Reset the flag when connection is established // Reset the flag when connection is established
hasReceivedInitialMessage = false; hasReceivedInitialMessage = false;
@ -965,7 +982,7 @@
event.code, event.code,
event.reason, event.reason,
); );
updateConnectionStatus("disconnected", "❌ Desconectado"); updateConnectionStatus("disconnected");
if (reconnectAttempts < maxReconnectAttempts) { if (reconnectAttempts < maxReconnectAttempts) {
reconnectAttempts++; reconnectAttempts++;
@ -975,56 +992,40 @@
); );
reconnectTimeout = setTimeout(() => { reconnectTimeout = setTimeout(() => {
updateConnectionStatus( updateConnectionStatus("connecting");
"connecting",
`🔄 Reconectando... (${reconnectAttempts}/${maxReconnectAttempts})`,
);
connectWebSocket(); connectWebSocket();
}, delay); }, delay);
} else { } else {
updateConnectionStatus( updateConnectionStatus("disconnected");
"disconnected",
"❌ Conexão perdida",
);
} }
}; };
ws.onerror = function (error) { ws.onerror = function (error) {
console.error("WebSocket error:", error); console.error("WebSocket error:", error);
updateConnectionStatus( updateConnectionStatus("disconnected");
"disconnected",
"❌ Erro de conexão",
);
}; };
} }
function processMessageContent(response) { function processMessageContent(response) {
// Check if this is the initial message after start // Clear empty state when we receive any message
if ( const emptyState = document.getElementById("emptyState");
!hasReceivedInitialMessage && if (emptyState) {
response.content && emptyState.remove();
response.content.trim()
) {
hasReceivedInitialMessage = true;
// Clear empty state and display the initial message
const emptyState = document.getElementById("emptyState");
if (emptyState) {
emptyState.remove();
}
// Add the initial message as a complete message
addMessage("assistant", response.content, false);
return;
} }
// Handle complete messages
if (response.is_complete) { if (response.is_complete) {
if (isStreaming && currentStreamingContent.trim()) { if (isStreaming) {
finalizeStreamingMessage(); finalizeStreamingMessage();
isStreaming = false;
streamingMessageId = null;
currentStreamingContent = "";
} else {
// This is a complete message that wasn't being streamed
addMessage("assistant", response.content, false);
} }
isStreaming = false;
streamingMessageId = null;
currentStreamingContent = "";
} else { } else {
// Handle streaming messages
if (!isStreaming) { if (!isStreaming) {
isStreaming = true; isStreaming = true;
streamingMessageId = "streaming-" + Date.now(); streamingMessageId = "streaming-" + Date.now();