// 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 { Button } from "~/components/ui/button"; import { Card, CardDescription, CardHeader, CardTitle, } from "~/components/ui/card"; import { fastForwardReplay } from "~/core/api"; import type { Option } from "~/core/messages"; import { useReplay } from "~/core/replay"; import { sendMessage, useStore } from "~/core/store"; import { cn } from "~/lib/utils"; import { ConversationStarter } from "./conversation-starter"; import { InputBox } from "./input-box"; import { MessageListView } from "./message-list-view"; import { RainbowText } from "./rainbow-text"; 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 [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(() => { console.info("cancel"); 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 && ( )}
) : ( <>
Replay Mode {responding ? "DeerFlow is now replaying the conversation..." : replayStarted ? "The replay has been stopped." : `You're now in DeerFlow's replay mode. Click the start button on the right to replay.`}
{responding && ( )} {!replayStarted && ( )}
)}
); }