'use client' import { type ComponentProps, createContext, type ReactNode, type SyntheticEvent, use, useEffect, useEffectEvent, useMemo, useRef, useState } from 'react' import { Loader2, MessageCircleIcon, RefreshCw, SearchIcon, Send, X } from 'lucide-react' import { cn } from '../../lib/cn' import { buttonVariants } from '../ui/button' import { useChat, type UseChatHelpers } from '@ai-sdk/react' import { DefaultChatTransport, type Tool, type UIToolInvocation } from 'ai' import { Markdown } from '../markdown' import { Presence } from '@radix-ui/react-presence' import type { ChatUIMessage, SearchTool } from '../../pages/_api/api/chat' const Context = createContext<{ open: boolean setOpen: (open: boolean) => void chat: UseChatHelpers } | null>(null) export function AISearchPanelHeader({ className, ...props }: ComponentProps<'div'>) { const { setOpen } = useAISearchContext() return (

AI Chat

AI can be inaccurate, please verify the answers.

) } export function AISearchInputActions() { const { messages, status, setMessages, regenerate } = useChatContext() const isLoading = status === 'streaming' if (messages.length === 0) return null return ( <> {!isLoading && messages.at(-1)?.role === 'assistant' && ( )} ) } const StorageKeyInput = '__ai_search_input' export function AISearchInput(props: ComponentProps<'form'>) { const { status, sendMessage, stop } = useChatContext() const [input, setInput] = useState(() => localStorage.getItem(StorageKeyInput) ?? '') const isLoading = status === 'streaming' || status === 'submitted' const onStart = (e?: SyntheticEvent) => { e?.preventDefault() const message = input.trim() if (message.length === 0) return void sendMessage({ role: 'user', parts: [ { type: 'data-client', data: { location: location.href } }, { type: 'text', text: message } ] }) setInput('') localStorage.removeItem(StorageKeyInput) } useEffect(() => { if (isLoading) document.getElementById('nd-ai-input')?.focus() }, [isLoading]) return (
{ setInput(e.target.value) localStorage.setItem(StorageKeyInput, e.target.value) }} onKeyDown={(event) => { if (!event.shiftKey && event.key === 'Enter') { onStart(event) } }} /> {isLoading ? ( ) : ( )}
) } function List(props: Omit, 'dir'>) { const containerRef = useRef(null) useEffect(() => { if (!containerRef.current) return function callback() { const container = containerRef.current if (!container) return container.scrollTo({ top: container.scrollHeight, behavior: 'instant' }) } const observer = new ResizeObserver(callback) callback() const element = containerRef.current?.firstElementChild if (element) { observer.observe(element) } return () => { observer.disconnect() } }, []) return (
{props.children}
) } function Input(props: ComponentProps<'textarea'>) { const ref = useRef(null) const shared = cn('col-start-1 row-start-1', props.className) return (