fix: duplicate assistant replies and flickering conversation list - #6
Open
naruto-91 wants to merge 1 commit into
Open
fix: duplicate assistant replies and flickering conversation list#6naruto-91 wants to merge 1 commit into
naruto-91 wants to merge 1 commit into
Conversation
ASahu16
self-requested a review
August 28, 2026 11:52
ASahu16
requested changes
Aug 28, 2026
ASahu16
left a comment
Collaborator
There was a problem hiding this comment.
@naruto-91 I'm not fully convinced this is the right fix here. It feels more like it's addressing the symptom than the underlying cause.
One concern: capping the reasoning budget this way stops the duplicate-reply/retry failure, but it also means the model has noticeably less room to actually think on harder queries. I'd expect that to show up as shallower or lower-quality answers on the more complex cases, even though the crash itself goes away trading one visible bug for a quieter one.
@PrashantShuklaa, @predator094 could you take a look too when you get a chance? Want a second pair of eyes before this goes in.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's fixed
1. Backend: assistant reply duplicated, then run fails with "Exceeded maximum output retries"
Root cause: Gemini's thinking models draw reasoning tokens from the same
budget as
max_tokens. On the post-tool-call turn, the model could burn theentire 8192-token cap thinking and return neither text nor a tool call.
pydantic-ai treats that as invalid output and force-retries — the model
re-answers the whole turn from scratch (full text + all display-tool calls
again), which the streaming layer forwards verbatim, so the user sees the
reply twice. The retry fails the same way a second time and the run dies with
UnexpectedModelBehavior: Exceeded maximum output retries (1).Fix (
backend/src/agent/builder.py): cap reasoning explicitly, perprovider, on the same branch that already selects the model —
google_thinking_config.thinking_budget=8192, withmax_tokensraised to 16384 so real output always has headroom left over.
openai_reasoning_effort="low".2. Frontend: conversation list refetched (and visibly flashed) on every load and thread switch
Root cause:
ConversationSidebarhad two effects both firing on mount —a
[fetchPage]mount effect and a[activeThreadId, fetchPage]effect meantto refresh the list after switching threads. Effects with no prior render to
diff against always run on mount regardless of deps, so every page load fired
/api/conversationstwice, and the second effect'sfetchPage(1)also setloading=true, blanking the whole list behind skeleton rows — visible as"the chat list refreshes" every time a chat was clicked.
Fix (
frontend/app/components/ConversationSidebar.tsx):didMountref — no moreduplicate fetch on initial load.
silentfetch mode used by that background refresh so it updatesdata without touching
loading/error— list stays on screen, no skeletonflash, while it still quietly re-syncs title/message-count after a switch.
Verification
backend:pytest— 71 passed, 2 deselected, 2 xfailed (no regressions)backend: agent builds successfully against both provider branchesfrontend:tsc --noEmit— clean