From c1a72a0c583096c60d71c882c8aa3f5f8acff4ed Mon Sep 17 00:00:00 2001
From: "google-labs-jules[bot]"
<161369871+google-labs-jules[bot]@users.noreply.github.com>
Date: Thu, 14 Aug 2025 06:43:44 +0000
Subject: [PATCH 1/2] Fix duplicate output in chat system
This commit fixes two sources of duplicate output in the chat system:
1. **Duplicate user messages:** The client-side components (`ChatPanel` and `SearchRelated`) were optimistically adding your messages to the UI state before the server had processed them. This resulted in your message appearing twice. This commit removes the optimistic UI updates, making the server the single source of truth for the chat history.
2. **Duplicate assistant responses:** I discovered that in some situations, I was adding the `answerSection` to the UI stream twice. I've added a condition to prevent this, ensuring the final answer is rendered only once.
---
components/chat-panel.tsx | 7 -------
components/search-related.tsx | 11 +----------
lib/agents/researcher.tsx | 6 +++++-
3 files changed, 6 insertions(+), 18 deletions(-)
diff --git a/components/chat-panel.tsx b/components/chat-panel.tsx
index c83f4445..8a69dbad 100644
--- a/components/chat-panel.tsx
+++ b/components/chat-panel.tsx
@@ -50,13 +50,6 @@ export function ChatPanel({ messages, input, setInput }: ChatPanelProps) {
handleClear()
setIsButtonPressed(false)
}
- setMessages(currentMessages => [
- ...currentMessages,
- {
- id: nanoid(),
- component:
- }
- ])
const formData = new FormData(e.currentTarget)
// Removed mcp argument from submit call
const responseMessage = await submit(formData)
diff --git a/components/search-related.tsx b/components/search-related.tsx
index b65a7be3..2bb49a79 100644
--- a/components/search-related.tsx
+++ b/components/search-related.tsx
@@ -41,18 +41,9 @@ export const SearchRelated: React.FC = ({
query = submitter.value
}
- const userMessage = {
- id: Date.now(),
- component:
- }
-
// Removed mcp argument from submit call
const responseMessage = await submit(formData)
- setMessages(currentMessages => [
- ...currentMessages,
- userMessage,
- responseMessage
- ])
+ setMessages(currentMessages => [...currentMessages, responseMessage])
}
return (
diff --git a/lib/agents/researcher.tsx b/lib/agents/researcher.tsx
index 6ef6d53b..6394ffe5 100644
--- a/lib/agents/researcher.tsx
+++ b/lib/agents/researcher.tsx
@@ -71,7 +71,11 @@ Match the language of your response to the user's language.`;
case 'text-delta':
if (delta.textDelta) {
// If the first text delta is available, add a UI section
- if (fullResponse.length === 0 && delta.textDelta.length > 0) {
+ if (
+ fullResponse.length === 0 &&
+ delta.textDelta.length > 0 &&
+ !useSpecificModel
+ ) {
// Update the UI
uiStream.update(answerSection)
}
From 281d5be4f68a3569c05491e7380b2dd40e827fe3 Mon Sep 17 00:00:00 2001
From: "google-labs-jules[bot]"
<161369871+google-labs-jules[bot]@users.noreply.github.com>
Date: Thu, 14 Aug 2025 10:00:57 +0000
Subject: [PATCH 2/2] Fix question preview and followup panel bugs
I've addressed two issues with this latest commit:
1. **Question preview not working:** A recent change to fix duplicate output inadvertently broke the question preview functionality. This was due to a misunderstanding of how to handle streamable values on the server. I've refactored the `Copilot` component and related server-side code to use streamable values correctly, which restores the question preview.
2. **Duplicate user messages in followup panel:** The `FollowupPanel` component was still using an optimistic UI update, which could cause duplicate user messages. I removed this optimistic update, making it consistent with the other input components.
---
components/copilot.tsx | 19 +++++-----
components/followup-panel.tsx | 12 +------
lib/agents/inquire.tsx | 67 ++++++++++++++---------------------
3 files changed, 36 insertions(+), 62 deletions(-)
diff --git a/components/copilot.tsx b/components/copilot.tsx
index af110a89..04408ee0 100644
--- a/components/copilot.tsx
+++ b/components/copilot.tsx
@@ -16,16 +16,17 @@ import {
} from './ui/icons'
import { cn } from '@/lib/utils'
+import { StreamableValue } from 'ai/rsc'
+
export type CopilotProps = {
- inquiry: { value: PartialInquiry };
+ inquiry: StreamableValue
}
-export const Copilot: React.FC = ({ inquiry }: CopilotProps) => {
- const { value } = inquiry;
+export const Copilot: React.FC = ({ inquiry }) => {
+ const [data, error, pending] = useStreamableValue(inquiry)
const [completed, setCompleted] = useState(false)
const [query, setQuery] = useState('')
const [skipped, setSkipped] = useState(false)
- const [data, error, pending] = useStreamableValue()
const [checkedOptions, setCheckedOptions] = useState<{
[key: string]: boolean
}>({})
@@ -121,14 +122,12 @@ export const Copilot: React.FC = ({ inquiry }: CopilotProps) => {