fix: many minor fixes

This commit is contained in:
Henry Li
2026-01-25 21:57:57 +08:00
parent ae0e7de3b7
commit 598fed797f
4 changed files with 83 additions and 38 deletions

View File

@@ -34,6 +34,14 @@ export async function GET(
headers,
});
}
if (artifactPath.endsWith(".mp4")) {
return new Response(fs.readFileSync(artifactPath), {
status: 200,
headers: {
"Content-Type": "video/mp4",
},
});
}
return new Response(fs.readFileSync(artifactPath), { status: 200 });
}
}

View File

@@ -93,6 +93,13 @@ export default function ChatPage() {
thread.values.artifacts,
]);
const artifactPanelOpen = useMemo(() => {
if (env.NEXT_PUBLIC_STATIC_WEBSITE_ONLY === "true") {
return artifactsOpen && artifacts?.length > 0;
}
return artifactsOpen;
}, [artifactsOpen, artifacts]);
const [todoListCollapsed, setTodoListCollapsed] = useState(
env.NEXT_PUBLIC_STATIC_WEBSITE_ONLY !== "true",
);
@@ -119,8 +126,8 @@ export default function ChatPage() {
<ResizablePanelGroup orientation="horizontal">
<ResizablePanel
className="relative"
defaultSize={artifactsOpen && artifacts?.length > 0 ? 46 : 100}
minSize={artifactsOpen && artifacts?.length > 0 ? 30 : 100}
defaultSize={artifactPanelOpen ? 46 : 100}
minSize={artifactPanelOpen ? 30 : 100}
>
<div className="relative flex size-full min-h-0 justify-between">
<header
@@ -215,9 +222,7 @@ export default function ChatPage() {
<ResizableHandle
className={cn(
"opacity-33 hover:opacity-100",
!artifactsOpen &&
artifacts?.length > 0 &&
"pointer-events-none opacity-0",
!artifactPanelOpen && "pointer-events-none opacity-0",
)}
/>
<ResizablePanel
@@ -225,16 +230,14 @@ export default function ChatPage() {
"transition-all duration-300 ease-in-out",
!artifactsOpen && "opacity-0",
)}
defaultSize={artifactsOpen && artifacts?.length > 0 ? 64 : 0}
defaultSize={artifactPanelOpen ? 64 : 0}
minSize={0}
maxSize={artifactsOpen && artifacts?.length > 0 ? undefined : 0}
maxSize={artifactPanelOpen ? undefined : 0}
>
<div
className={cn(
"h-full p-4 transition-transform duration-300 ease-in-out",
artifactsOpen && artifacts?.length > 0
? "translate-x-0"
: "translate-x-full",
artifactPanelOpen ? "translate-x-0" : "translate-x-full",
)}
>
{selectedArtifact ? (

View File

@@ -1,40 +1,48 @@
import { SparklesIcon } from "lucide-react";
import Link from "next/link";
import SpotlightCard from "@/components/ui/spotlight-card";
import { Card } from "@/components/ui/card";
import { pathOfThread } from "@/core/threads/utils";
import { cn } from "@/lib/utils";
import { Section } from "../section";
export function CaseStudySection({ className }: { className?: string }) {
const caseStudies = [
{
title: "2025 Survey",
threadId: "7cfa5f8f-a2f8-47ad-acbd-da7137baf990",
title: "Forecast 2026 Agent Trends and Opportunities",
description:
"A 12,000-word research report analyzing 47 papers on brain-inspired chips, covering Intel Loihi 2, IBM NorthPole, and SynSense's edge AI solutions.",
"Create a webpage with a Deep Research report forecasting the agent technology trends and opportunities in 2026.",
},
{
title: "Indie Hacker's SaaS Landing Page",
threadId: "4f3e55ee-f853-43db-bfb3-7d1a411f03cb",
title: 'Generate a Video Based On the Novel "Pride and Prejudice"',
description:
"A fully responsive landing page with hero section, pricing table, testimonials, and Stripe integration — shipped in one conversation.",
'Search the specific scene from the novel "Pride and Prejudice", then generate a video as well as a reference image based on the scenes.',
},
{
title: "Transformer Architecture Explained",
threadId: "21cfea46-34bd-4aa6-9e1f-3009452fbeb9",
title: "Doraemon Explains the MOE Architecture",
description:
"A 25-slide presentation breaking down self-attention, positional encoding, and KV-cache with hand-drawn style diagrams for a university lecture.",
"Generate a Doraemon comic strip explaining the MOE architecture to the teenagers who are interested in AI.",
},
{
title: "DeerDeer Explains RAG",
threadId: "ad76c455-5bf9-4335-8517-fc03834ab828",
title: "An Exploratory Data Analysis of the Titanic Dataset",
description:
"A series of 12 illustrations featuring a curious deer mascot explaining Retrieval-Augmented Generation through a library adventure story.",
"Explore the Titanic dataset and identify the key factors that influenced survival rates with visualizations and insights.",
},
{
title: "AI Weekly: Your Tech Podcast",
threadId: "d3e5adaf-084c-4dd5-9d29-94f1d6bccd98",
title: "Watch Y Combinator's Video then Conduct a Deep Research",
description:
"A 20-minute podcast episode where two AI hosts debate whether AI agents will replace traditional SaaS, based on 5 articles you provided.",
"Watch the given Y Combinator's YouTube video and conduct a deep research on the YC's tips for technical startup founders.",
},
{
title: "How Diffusion Models Work",
threadId: "3823e443-4e2b-4679-b496-a9506eae462b",
title: "Collect and Summarize Dr. Fei Fei Li's Podcasts",
description:
"A 3-minute animated explainer video visualizing the denoising process, from pure noise to a generated image, with voiceover narration.",
"Collect all the podcast appearances of Dr. Fei Fei Li in the last 6 months, then summarize them into a comprehensive report.",
},
];
return (
@@ -43,23 +51,46 @@ export function CaseStudySection({ className }: { className?: string }) {
title="Case Studies"
subtitle="See how DeerFlow is used in the wild"
>
<div className="mt-8 grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
<div className="container-md mt-8 grid grid-cols-1 gap-4 px-20 md:grid-cols-2 lg:grid-cols-3">
{caseStudies.map((caseStudy) => (
<SpotlightCard className="h-64" key={caseStudy.title}>
<div className="flex h-full w-full flex-col items-center justify-center">
<div className="flex w-75 flex-col gap-4">
<div>
<SparklesIcon className="text-primary size-8" />
</div>
<div className="flex flex-col gap-2">
<h3 className="text-2xl font-bold">{caseStudy.title}</h3>
<p className="text-muted-foreground text-sm">
{caseStudy.description}
</p>
<Link
key={caseStudy.title}
href={pathOfThread(caseStudy.threadId)}
target="_blank"
>
<Card className="group/card relative h-64 overflow-hidden">
<div
className="absolute inset-0 z-0 bg-cover bg-center bg-no-repeat transition-all duration-300 group-hover/card:scale-110 group-hover/card:brightness-90"
style={{
backgroundImage: `url(/images/${caseStudy.threadId}.jpg)`,
}}
></div>
<div
className={cn(
"flex h-full w-full translate-y-[calc(100%-60px)] flex-col items-center",
"transition-all duration-300",
"group-hover/card:translate-y-[calc(100%-128px)]",
)}
>
<div
className="flex w-full flex-col p-4"
style={{
background:
"linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 100%)",
}}
>
<div className="flex flex-col gap-2">
<h3 className="flex h-14 items-center text-xl font-bold text-shadow-black">
{caseStudy.title}
</h3>
<p className="box-shadow-black overflow-hidden text-sm text-white/85 text-shadow-black">
{caseStudy.description}
</p>
</div>
</div>
</div>
</div>
</SpotlightCard>
</Card>
</Link>
))}
</div>
</Section>

View File

@@ -11,9 +11,11 @@ interface Position {
interface SpotlightCardProps extends React.PropsWithChildren {
className?: string;
spotlightColor?: `rgba(${number}, ${number}, ${number}, ${number})`;
style?: React.CSSProperties;
}
const SpotlightCard: React.FC<SpotlightCardProps> = ({
style,
children,
className = "",
spotlightColor = "rgba(255, 255, 255, 0.25)",
@@ -37,6 +39,7 @@ const SpotlightCard: React.FC<SpotlightCardProps> = ({
ref={divRef}
onMouseMove={handleMouseMove}
className={`card-spotlight ${className}`}
style={style}
>
{children}
</div>