"use client"; import { Button } from "@/components/ui/button"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import { List, HelpCircle } from "lucide-react"; import { cn } from "@/lib/utils"; import { useState } from "react"; import { PlanItem, TaskPlan } from "@open-swe/shared/open-swe/types"; import { HoverCard, HoverCardContent, HoverCardTrigger, } from "@/components/ui/hover-card"; interface ProgressBarProps { taskPlan?: TaskPlan; className?: string; onOpenSidebar?: () => void; } export function ProgressBar({ taskPlan, className, onOpenSidebar, }: ProgressBarProps) { const [showLegend, setShowLegend] = useState(false); if (!taskPlan || !taskPlan.tasks.length) { return (
No active plan
); } const currentTask = taskPlan.tasks[taskPlan.activeTaskIndex]; if (!currentTask || !currentTask.planRevisions.length) { return (
No active plan
); } const activeRevision = currentTask.planRevisions[currentTask.activeRevisionIndex]; const planItems = [...activeRevision.plans].sort((a, b) => a.index - b.index); // Find the current task (lowest index among uncompleted tasks) const currentTaskIndex = planItems .filter((item) => !item.completed) .reduce( (min, item) => (item.index < min ? item.index : min), Number.POSITIVE_INFINITY, ); const getItemState = ( item: PlanItem, ): "completed" | "current" | "remaining" => { if (item.completed) return "completed"; if (item.index === currentTaskIndex) return "current"; return "remaining"; }; const completedCount = planItems.filter((item) => item.completed).length; const progressPercentage = planItems.length > 0 ? (completedCount / planItems.length) * 100 : 0; const getSegmentColor = (state: string) => { switch (state) { case "completed": return "bg-green-400"; case "current": return "bg-blue-400"; default: return "bg-gray-200"; } }; return (
{/* Compact header */}
Plan Progress

Plan Progress

Shows the current progress of the AI agent's plan execution.

{Math.round(progressPercentage)}%
{/* Legend - conditionally shown */} {showLegend && (
Completed
Current
Pending
)} {/* Progress Stats */}
{completedCount} of {planItems.length} tasks completed Task #{currentTask.taskIndex + 1}
{/* Progress Bar */}
{planItems.map((item) => { const state = getItemState(item); const segmentWidth = `${100 / planItems.length}%`; return (
Task #{item.index + 1} {state === "completed" ? "Completed" : state === "current" ? "Current" : "Pending"}

{item.plan}

); })}
); }