+}
+
+export function SearchSection({ result }: SearchSectionProps) {
+ const [data, error, pending] = useStreamableValue(result)
+ const results: TypeSearchResults = data ? JSON.parse(data) : undefined
+ return (
+
+ {!pending && data ? (
+ <>
+
+ {results.images && results.images.length > 0 && (
+
+ )}
+
+ >
+ ) : (
+
+ )}
+
+ )
+}
diff --git a/lib/agents/researcher.tsx b/lib/agents/researcher.tsx
index 924782dd..ca3b7824 100644
--- a/lib/agents/researcher.tsx
+++ b/lib/agents/researcher.tsx
@@ -8,13 +8,11 @@ import {
import { searchSchema } from '@/lib/schema/search'
import { Section } from '@/components/section'
import { OpenAI } from '@ai-sdk/openai'
-import { ToolBadge } from '@/components/tool-badge'
-import { SearchSkeleton } from '@/components/search-skeleton'
-import { SearchResults } from '@/components/search-results'
import { BotMessage } from '@/components/message'
import Exa from 'exa-js'
-import { SearchResultsImageSection } from '@/components/search-results-image'
import { Card } from '@/components/ui/card'
+import { SearchResults } from '../types'
+import { SearchSection } from '@/components/search-section'
export async function researcher(
uiStream: ReturnType,
@@ -38,6 +36,7 @@ export async function researcher(
)
+ let isFirstToolResponse = true
const result = await experimental_streamText({
model: openai.chat(process.env.OPENAI_API_MODEL || 'gpt-4-turbo'),
maxTokens: 2500,
@@ -61,17 +60,14 @@ export async function researcher(
max_results: number
search_depth: 'basic' | 'advanced'
}) => {
- uiStream.update(
-
- )
-
- uiStream.append(
-
- )
+ // If this is the first tool response, remove spinner
+ if (isFirstToolResponse) {
+ isFirstToolResponse = false
+ uiStream.update(null)
+ }
+ // Append the search section
+ const streamResults = createStreamableValue()
+ uiStream.append()
// Tavily API requires a minimum of 5 characters in the query
const filledQuery =
@@ -97,24 +93,7 @@ export async function researcher(
return searchResult
}
- uiStream.update(
-
- )
- uiStream.append(
-
- )
-
- // Append the answer section if the specific model is not used
- if (!useSpecificModel) {
- uiStream.append(answerSection)
- }
+ streamResults.done(JSON.stringify(searchResult))
return searchResult
}
@@ -142,6 +121,10 @@ export async function researcher(
toolCalls.push(delta)
break
case 'tool-result':
+ // Append the answer section if the specific model is not used
+ if (!useSpecificModel && toolResponses.length === 0) {
+ uiStream.append(answerSection)
+ }
toolResponses.push(delta)
break
case 'error':
diff --git a/lib/types/index.ts b/lib/types/index.ts
new file mode 100644
index 00000000..43cb522a
--- /dev/null
+++ b/lib/types/index.ts
@@ -0,0 +1,11 @@
+export type SearchResults = {
+ images: string[]
+ results: SearchResultItem[]
+ query: string
+}
+
+export type SearchResultItem = {
+ title: string
+ url: string
+ content: string
+}