"use client"; import { memo } from "react"; import { differenceInHours, differenceInMinutes, format } from "date-fns"; import { GitBranch, ArrowRight, ListTodo } from "lucide-react"; import { useThreads } from "@/providers/Thread"; import { cn } from "@/lib/utils"; import { StatusIndicator } from "@/components/status-indicator"; import { GitHubSVG } from "./icons/github"; import { useQueryState } from "nuqs"; import { Thread } from "@langchain/langgraph-sdk"; import { GraphState } from "@open-swe/shared/open-swe/types"; import { getThreadTasks, getThreadTitle } from "@/lib/thread"; interface ThreadItemProps { thread: Thread; onClick: (thread: Thread) => void; variant?: "sidebar" | "dashboard"; className?: string; } function formatRelativeDate(dateString: string): string { const date = new Date(dateString); const now = new Date(); const minutesAgo = differenceInMinutes(now, date); const hoursAgo = differenceInHours(now, date); // Within the last hour - show minutes ago if (minutesAgo < 60) { return `${minutesAgo} min ago`; } // Between 1-24 hours ago - show hours ago if (hoursAgo < 24) { return `${hoursAgo} hour${hoursAgo === 1 ? "" : "s"} ago`; } // More than 24 hours ago - show month, day format return format(date, "MMM do"); } export const ThreadItem = memo(function ThreadItem({ thread, onClick, variant = "dashboard", className, }: ThreadItemProps) { const [threadId] = useQueryState("threadId"); const { recentlyUpdatedThreads } = useThreads(); const isSelected = thread.thread_id === threadId; const isSidebar = variant === "sidebar"; const isRecentlyUpdated = recentlyUpdatedThreads.has(thread.thread_id); const displayDate = formatRelativeDate(thread.created_at); const { totalTasks, completedTasks } = getThreadTasks(thread); return (
{ if (!isSelected) { onClick(thread); } }} >

{getThreadTitle(thread)}

{thread.values.targetRepository.repo} / {thread.values.targetRepository.branch}
• {displayDate} {!isSidebar && ( <> •
{completedTasks}/{totalTasks} tasks
)}
{isSidebar && (
{completedTasks}/{totalTasks} tasks
)}
); });