diff --git a/ui/client-app/src/components/ChatWindow.css b/ui/client-app/src/components/ChatWindow.css index 8b923b7..910f1c5 100644 --- a/ui/client-app/src/components/ChatWindow.css +++ b/ui/client-app/src/components/ChatWindow.css @@ -73,7 +73,7 @@ border-radius: 0.75rem; } -.thinking-dots::after { +.streaming-dots::after { content: ''; animation: dots 1.5s steps(5, end) infinite; } diff --git a/ui/client-app/src/components/ChatWindow.js b/ui/client-app/src/components/ChatWindow.js index f7fc8f0..5a9d002 100644 --- a/ui/client-app/src/components/ChatWindow.js +++ b/ui/client-app/src/components/ChatWindow.js @@ -104,13 +104,13 @@
- + {message.status}
)} - {message.reasoning && ( + {(message.reasoning || (message.status === "Thinking")) && (
+
[...prev, { isUser: true, text, timestamp: new Date().toISOString() }]); try { - const startTime = Date.now(); let reasoningStartTime = null; let reasoningDuration = 0; - // Add a placeholder message for the AI that we will update live + // Add a placeholder message for the AI starting with 'Generating' status setChatHistory((prev) => [...prev, { isUser: false, text: "", reasoning: "", - status: "Thinking", // CSS animation will add the dots + status: "Generating", // Initially show 'Generating' provider: localActiveLLM, timestamp: new Date().toISOString() }]); @@ -157,13 +156,14 @@ if (event.type === "reasoning") { if (!reasoningStartTime) reasoningStartTime = Date.now(); lastMsg.reasoning += event.content; - lastMsg.status = "Thinking"; + lastMsg.status = "Thinking"; // Switch to Thinking if reasoning tokens arrive } else if (event.type === "content") { if (reasoningStartTime && !lastMsg.thoughtDone) { reasoningDuration = Math.round((Date.now() - reasoningStartTime) / 1000); lastMsg.status = `Thought for ${reasoningDuration}s`; lastMsg.thoughtDone = true; - } else if (!reasoningStartTime) { + } else if (!reasoningStartTime && lastMsg.status === "Generating") { + // Direct answer case: hide status once tokens start arriving lastMsg.status = null; } lastMsg.text += event.content; @@ -188,6 +188,7 @@ setIsProcessing(false); } + }, [isConfigured, localActiveLLM, fetchTokenUsage]); const handleSwitchSession = useCallback(async (targetSessionId) => {