// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: MIT import { motion } from "framer-motion"; import { FastForward, Play } from "lucide-react"; import { useCallback, useRef, useState } from "react"; import { RainbowText } from "~/components/deer-flow/rainbow-text"; import { Button } from "~/components/ui/button"; import { Card, CardDescription, CardHeader, CardTitle, } from "~/components/ui/card"; import { fastForwardReplay } from "~/core/api"; import { useReplayMetadata } from "~/core/api/hooks"; import type { Option } from "~/core/messages"; import { useReplay } from "~/core/replay"; import { sendMessage, useStore } from "~/core/store"; import { env } from "~/env"; import { cn } from "~/lib/utils"; import { ConversationStarter } from "./conversation-starter"; import { InputBox } from "./input-box"; import { MessageListView } from "./message-list-view"; import { Welcome } from "./welcome"; export function MessagesBlock({ className }: { className?: string }) { const messageCount = useStore((state) => state.messageIds.length); const responding = useStore((state) => state.responding); const { isReplay } = useReplay(); const { title: replayTitle, hasError: replayHasError } = useReplayMetadata(); const [replayStarted, setReplayStarted] = useState(false); const abortControllerRef = useRef(null); const [feedback, setFeedback] = useState<{ option: Option } | null>(null); const handleSend = useCallback( async (message: string, options?: { interruptFeedback?: string }) => { const abortController = new AbortController(); abortControllerRef.current = abortController; try { await sendMessage( message, { interruptFeedback: options?.interruptFeedback ?? feedback?.option.value, }, { abortSignal: abortController.signal, }, ); } catch {} }, [feedback], ); const handleCancel = useCallback(() => { abortControllerRef.current?.abort(); abortControllerRef.current = null; }, []); const handleFeedback = useCallback( (feedback: { option: Option }) => { setFeedback(feedback); }, [setFeedback], ); const handleRemoveFeedback = useCallback(() => { setFeedback(null); }, [setFeedback]); const handleStartReplay = useCallback(() => { setReplayStarted(true); void sendMessage(); }, [setReplayStarted]); const [fastForwarding, setFastForwarding] = useState(false); const handleFastForwardReplay = useCallback(() => { setFastForwarding(!fastForwarding); fastForwardReplay(!fastForwarding); }, [fastForwarding]); return (
{!isReplay ? (
{!responding && messageCount === 0 && ( )}
) : ( <>
{responding ? "Replaying" : `${replayTitle}`} {responding ? "DeerFlow is now replaying the conversation..." : replayStarted ? "The replay has been stopped." : `You're now in DeerFlow's replay mode. Click the "Play" button on the right to start.`}
{!replayHasError && (
{responding && ( )} {!replayStarted && ( )}
)}
{!replayStarted && env.NEXT_PUBLIC_STATIC_WEBSITE_ONLY && (
* This site is for demo purposes only. If you want to try your own question, please{" "} click here {" "} to clone it locally and run it.
)}
)}
); }