feat: add Replay Mode

This commit is contained in:
Li Xin
2025-04-24 21:51:08 +08:00
parent 3735706065
commit cb4b7b7495
10 changed files with 1035 additions and 40 deletions

View File

@@ -1,8 +1,15 @@
// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
// SPDX-License-Identifier: MIT
import { useSearchParams } from "next/navigation";
import { useCallback, useRef, useState } from "react";
import {
Card,
CardDescription,
CardHeader,
CardTitle,
} from "~/components/ui/card";
import type { Option } from "~/core/messages";
import { sendMessage, useStore } from "~/core/store";
import { cn } from "~/lib/utils";
@@ -10,10 +17,12 @@ 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";
export function MessagesBlock({ className }: { className?: string }) {
const messageCount = useStore((state) => state.messageIds.length);
const responding = useStore((state) => state.responding);
const replaying = useSearchParams().get("replay") !== null;
const abortControllerRef = useRef<AbortController | null>(null);
const [feedback, setFeedback] = useState<{ option: Option } | null>(null);
const handleSend = useCallback(
@@ -56,22 +65,39 @@ export function MessagesBlock({ className }: { className?: string }) {
onFeedback={handleFeedback}
onSendMessage={handleSend}
/>
<div className="relative flex h-42 shrink-0 pb-4">
{!responding && messageCount === 0 && (
<ConversationStarter
className="absolute top-[-218px] left-0"
{!replaying ? (
<div className="relative flex h-42 shrink-0 pb-4">
{!responding && messageCount === 0 && (
<ConversationStarter
className="absolute top-[-218px] left-0"
onSend={handleSend}
/>
)}
<InputBox
className="h-full w-full"
responding={responding}
feedback={feedback}
onSend={handleSend}
onCancel={handleCancel}
onRemoveFeedback={handleRemoveFeedback}
/>
)}
<InputBox
className="h-full w-full"
responding={responding}
feedback={feedback}
onSend={handleSend}
onCancel={handleCancel}
onRemoveFeedback={handleRemoveFeedback}
/>
</div>
</div>
) : (
<div className="flex h-42 w-full items-center justify-center">
<Card className="w-full">
<CardHeader>
<CardTitle>
<RainbowText animated={responding}>Replay Mode</RainbowText>
</CardTitle>
<CardDescription>
<RainbowText animated={responding}>
DeerFlow is now replaying the conversation...
</RainbowText>
</CardDescription>
</CardHeader>
</Card>
</div>
)}
</div>
);
}

View File

@@ -5,10 +5,11 @@
import { GithubOutlined } from "@ant-design/icons";
import Link from "next/link";
import { useMemo } from "react";
import { useEffect, useMemo } from "react";
import { Button } from "~/components/ui/button";
import { useStore } from "~/core/store";
import { useReplay } from "~/core/replay";
import { sendMessage, useStore } from "~/core/store";
import { cn } from "~/lib/utils";
import { Logo } from "./_components/logo";
@@ -19,11 +20,17 @@ import { Tooltip } from "./_components/tooltip";
import { SettingsDialog } from "./_settings/dialogs/settings-dialog";
export default function HomePage() {
const { isReplay } = useReplay();
const openResearchId = useStore((state) => state.openResearchId);
const doubleColumnMode = useMemo(
() => openResearchId !== null,
[openResearchId],
);
useEffect(() => {
if (isReplay) {
void sendMessage();
}
}, [isReplay]);
return (
<div className="flex h-full w-full justify-center">
<header className="fixed top-0 left-0 flex h-12 w-full w-screen items-center justify-between px-4">