'use client' import { UseChatHelpers } from '@ai-sdk/react' import { IconAlertCircle as AlertCircle, IconCheck as Check, IconExternalLink as ExternalLink, IconWorld as Globe } from '@tabler/icons-react' import { toPublicErrorPayload } from '@/lib/errors/public-error' import { SearchResults as SearchResultsType } from '@/lib/types' import type { ToolPart, UIDataTypes, UIMessage, UITools } from '@/lib/types/ai' import { cn } from '@/lib/utils' import ProcessHeader from './process-header' interface FetchSectionProps { tool: ToolPart<'fetch'> isOpen: boolean onOpenChange: (open: boolean) => void status?: UseChatHelpers>['status'] borderless?: boolean isFirst?: boolean isLast?: boolean } export function FetchSection({ tool, isOpen, // Required by ToolSection interface onOpenChange, // Required by ToolSection interface status, borderless = false, isFirst = false, isLast = false }: FetchSectionProps) { const url = tool.input?.url const isLoading = status === 'submitted' || status === 'streaming' const isToolLoading = tool.state === 'input-streaming' || tool.state === 'input-available' // Handle streaming output states const output = tool.state === 'output-available' ? tool.output : undefined const isFetching = output?.state === 'fetching' const fetchResults = output?.state === 'complete' ? output : undefined // Determine the status based on tool output availability let displayStatus: 'fetching' | 'success' | 'error' = 'fetching' let error: string | undefined let title: string | undefined let contentLength: number | undefined // Check tool state if (tool.state === 'output-error') { displayStatus = 'error' error = toPublicErrorPayload(tool.errorText, { fallbackMessage: 'Failed to retrieve content' }).error } else if (!output || isFetching) { displayStatus = 'fetching' } else if (fetchResults) { // Success state - we have complete output const data = fetchResults as SearchResultsType if (data?.results?.[0]) { displayStatus = 'success' title = data.results[0].title contentLength = data.results[0].content?.length } else { displayStatus = 'error' error = 'No content retrieved' } } // Get page title for display const getPageTitle = () => { if (title) return title if (!url) return 'Unknown URL' try { const domain = new URL(url).hostname return domain.replace('www.', '') } catch { return url } } // Handle click to open URL const handleClick = () => { if (url && displayStatus === 'success') { window.open(url, '_blank', 'noopener,noreferrer') } } const header = ( {getPageTitle()} } meta={ displayStatus === 'success' && contentLength ? ( <> {contentLength > 1000 ? `${Math.round(contentLength / 1000)}k chars` : `${contentLength} chars`} ) : displayStatus === 'error' ? ( <> {error} ) : isToolLoading ? ( Retrieving... ) : undefined } className={cn( displayStatus === 'success' && 'hover:text-foreground cursor-pointer' )} /> ) return (
{/* Rails for header - show based on position */} {borderless && ( <> {!isFirst && (
)} {!isLast && (
)} )} {/* Header only section - no collapsible body */}
{header}
{displayStatus === 'success' && ( )}
) } export default FetchSection