fix: Various Agent Stream Reasoning Bugs & Presentation Refactor#5677
Conversation
shatfield4
left a comment
There was a problem hiding this comment.
Seems to work just fine for me on the backend using tooled and untooled providers with reasoning enabled. Tested both Deepseek and Lemonade providers with thinking models in both regular chat and agent modes. Some small UI issues here with the copy button appearing under the thoughts UI (when pressing copy nothing is copied so we need to make sure we hide this in the UI or make it functional).
@shatfield4 I was able to fix this in bcfad04
|
shatfield4
left a comment
There was a problem hiding this comment.
Tested again and UI LGTM now.
|
@angelplusultra this seems to work well - however my only feedback is about the UI - I can understand wanting to break out thoughts but the very nature of thoughts is more like a debug log - they are ephemeral to understanding reasoning but we should collapse these into the Otherwise, worse case on multi-step is we get a list of thoughts/status alternating until finally the user gets an answer - which is a lot of waste screenspace when all the user wants is the real output! |
shatfield4
left a comment
There was a problem hiding this comment.
Is fully functional and now stacks all thoughts/agent calls into the single thoughts/agent call container.
I am noticing we are not seeing the animation being played though when thinking is in progress. Can you trigger the animation so it plays the animation while thinking is in progress?
timothycarambat
left a comment
There was a problem hiding this comment.
Let's look at the frontend changes here - I think we can simplify the diff here a lot. Feels like we are doing a lot of change for something that should, ideally, be smaller footprint



Pull Request Type
Relevant Issues
resolves #5676
UPSTREAM PR: #5972
TLDR
This PR fixes a few things:
tooledStreamanduntooledstream pathways (any provider emittingreasoning_content), instead of only Ollama.StatusResponsebubble (same place tool activity shows) and is ephemeral — a reloaded conversation shows only tool status + the final answer. This replaces the old<think>thought-pane that stacked a separate pane per step.tooledoruntooledstream pathways, instead its own bespoke implementation using</think>tags. It has been refactored to match the behavior intooledanduntooledDescription
In agent mode, only
ollamasurfaced reasoning — and it did so as a standalone<think>thought pane that was persisted into the saved message. Every other provider routing through the shared OpenAI-compatible helpers (tooled.js/untooled.js) droppedreasoning_contententirely, so users got a long pause then only the final answer.This PR does two things:
reasoning_content).StatusResponsebubble (the same place tool activity shows), framed with"Thinking:", and is no longer persisted — a reloaded conversation shows only tool status + the final answer. This replaces the old<think>thought-pane approach, which stacked a separate pane per step in multi-step runs (per review feedback).This is a behavior change for Ollama too: its agent reasoning used to render as a thought pane and survive reload, and is now ephemeral.
Scope:
tooledStream,UnTooled.stream/streamingFunctionCall) plus Ollama.anthropic.js,openai.js,gemini.js,bedrock.js.<think>panes. The agent/regular asymmetry is noted for a separate discussion.Implementation notes:
${msgUUID}:reasoning) so the answer'stextResponseChunkdoesn't merge into the reasoning bubble and render thoughts as visible text.visibleResponseContent()helper so reasoning-only bubbles don't get a copy button that copies an empty string.Agent head animation (pulse) fix:
The animated agent head is meant to pulse while the agent is actively thinking or invoking a tool, and go static once the final answer is streaming or the agent is idle. It was instead deriving "is the agent working" from the chat tail — pulse while a session is open and the last message is a status bubble. In an interactive
@agentsession the socket stays open between turns, so any turn that ended on a status bubble (e.g. an untooled reasoning turn that finished on a thought with no trailing answer) left the head pulsing forever.It now drives the animation off the live stream events instead of the rendered tail:
statusResponse(thinking) ortoolCallInvocationevent starts the pulse.textResponseChunk/fullTextResponse) or the end-of-turn markers (usageMetrics/chatId, which the agent backend emits at the end of every turn even when the answer is empty) settle it to static, as does a session start/end.This is tracked with a small
useIsAgentThinking()hook (mirroringuseIsAgentSessionActive) fed byAGENT_THINKING_START/AGENT_THINKING_STOPevents dispatched from the websocket handler.Untooled reasoning persistence fix:
In tooled mode the reasoning bubble persists after the answer lands (collapsible), but in untooled mode the thoughts disappeared the moment the response finished.
streamingFunctionCallwas streaming both the reasoning and the tentative tool-call/answer preview under the samemsgUUID, then callingremoveStatusResponse(msgUUID)to clear the preview once the turn resolved — which wiped the thoughts along with it. Reasoning now streams under its own${msgUUID}:reasoningbubble so the cleanup only removes the preview, matchingtooled.jsand the existing second-stream path.Visuals (if applicable)
Additional Information
Developer Validations
yarn lintfrom the root of the repo & committed changes