feat(assistant-steps): handle reading, search_results

This commit is contained in:
ItzCrazyKns
2025-12-08 13:08:26 +05:30
parent 331387efa4
commit 96001a9e26

View File

@@ -1,6 +1,13 @@
'use client'; 'use client';
import { Brain, Search, FileText, ChevronDown, ChevronUp } from 'lucide-react'; import {
Brain,
Search,
FileText,
ChevronDown,
ChevronUp,
BookSearch,
} from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion'; import { motion, AnimatePresence } from 'framer-motion';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { ResearchBlock, ResearchBlockSubStep } from '@/lib/types'; import { ResearchBlock, ResearchBlockSubStep } from '@/lib/types';
@@ -11,9 +18,12 @@ const getStepIcon = (step: ResearchBlockSubStep) => {
return <Brain className="w-4 h-4" />; return <Brain className="w-4 h-4" />;
} else if (step.type === 'searching') { } else if (step.type === 'searching') {
return <Search className="w-4 h-4" />; return <Search className="w-4 h-4" />;
} else if (step.type === 'reading') { } else if (step.type === 'search_results') {
return <FileText className="w-4 h-4" />; return <FileText className="w-4 h-4" />;
} else if (step.type === 'reading') {
return <BookSearch className="w-4 h-4" />;
} }
return null; return null;
}; };
@@ -25,9 +35,12 @@ const getStepTitle = (
return isStreaming && !step.reasoning ? 'Thinking...' : 'Thinking'; return isStreaming && !step.reasoning ? 'Thinking...' : 'Thinking';
} else if (step.type === 'searching') { } else if (step.type === 'searching') {
return `Searching ${step.searching.length} ${step.searching.length === 1 ? 'query' : 'queries'}`; return `Searching ${step.searching.length} ${step.searching.length === 1 ? 'query' : 'queries'}`;
} else if (step.type === 'reading') { } else if (step.type === 'search_results') {
return `Found ${step.reading.length} ${step.reading.length === 1 ? 'result' : 'results'}`; return `Found ${step.reading.length} ${step.reading.length === 1 ? 'result' : 'results'}`;
} else if (step.type === 'reading') {
return `Reading ${step.reading.length} ${step.reading.length === 1 ? 'source' : 'sources'}`;
} }
return 'Processing'; return 'Processing';
}; };
@@ -91,10 +104,9 @@ const AssistantSteps = ({
initial={{ opacity: 0, x: -10 }} initial={{ opacity: 0, x: -10 }}
animate={{ opacity: 1, x: 0 }} animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.2, delay: 0 }} transition={{ duration: 0.2, delay: 0 }}
className="flex gap-3" className="flex gap-2"
> >
{/* Timeline connector */} <div className="flex flex-col items-center -mt-0.5">
<div className="flex flex-col items-center pt-0.5">
<div <div
className={`rounded-full p-1.5 bg-light-100 dark:bg-dark-100 text-black/70 dark:text-white/70 ${isStreaming ? 'animate-pulse' : ''}`} className={`rounded-full p-1.5 bg-light-100 dark:bg-dark-100 text-black/70 dark:text-white/70 ${isStreaming ? 'animate-pulse' : ''}`}
> >
@@ -105,7 +117,6 @@ const AssistantSteps = ({
)} )}
</div> </div>
{/* Step content */}
<div className="flex-1 pb-1"> <div className="flex-1 pb-1">
<span className="text-sm font-medium text-black dark:text-white"> <span className="text-sm font-medium text-black dark:text-white">
{getStepTitle(step, isStreaming)} {getStepTitle(step, isStreaming)}
@@ -151,37 +162,39 @@ const AssistantSteps = ({
</div> </div>
)} )}
{step.type === 'reading' && step.reading.length > 0 && ( {(step.type === 'search_results' ||
<div className="flex flex-wrap gap-1.5 mt-1.5"> step.type === 'reading') &&
{step.reading.slice(0, 4).map((result, idx) => { step.reading.length > 0 && (
const url = result.metadata.url || ''; <div className="flex flex-wrap gap-1.5 mt-1.5">
const title = result.metadata.title || 'Untitled'; {step.reading.slice(0, 4).map((result, idx) => {
const domain = url ? new URL(url).hostname : ''; const url = result.metadata.url || '';
const faviconUrl = domain const title = result.metadata.title || 'Untitled';
? `https://s2.googleusercontent.com/s2/favicons?domain=${domain}&sz=128` const domain = url ? new URL(url).hostname : '';
: ''; const faviconUrl = domain
? `https://s2.googleusercontent.com/s2/favicons?domain=${domain}&sz=128`
: '';
return ( return (
<span <span
key={idx} key={idx}
className="inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md text-xs font-medium bg-light-100 dark:bg-dark-100 text-black/70 dark:text-white/70 border border-light-200 dark:border-dark-200" className="inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md text-xs font-medium bg-light-100 dark:bg-dark-100 text-black/70 dark:text-white/70 border border-light-200 dark:border-dark-200"
> >
{faviconUrl && ( {faviconUrl && (
<img <img
src={faviconUrl} src={faviconUrl}
alt="" alt=""
className="w-3 h-3 rounded-sm flex-shrink-0" className="w-3 h-3 rounded-sm flex-shrink-0"
onError={(e) => { onError={(e) => {
e.currentTarget.style.display = 'none'; e.currentTarget.style.display = 'none';
}} }}
/> />
)} )}
<span className="line-clamp-1">{title}</span> <span className="line-clamp-1">{title}</span>
</span> </span>
); );
})} })}
</div> </div>
)} )}
</div> </div>
</motion.div> </motion.div>
); );