diff --git a/apps/web/components/chat/research-progress.tsx b/apps/web/components/chat/research-progress.tsx deleted file mode 100644 index ad465ccb..00000000 --- a/apps/web/components/chat/research-progress.tsx +++ /dev/null @@ -1,212 +0,0 @@ -"use client" - -import { useState } from "react" -import { - ArrowRightIcon, - CheckCircle2Icon, - ChevronDownIcon, - ChevronUpIcon, - CircleHelpIcon, - CircleIcon, - Loader2Icon, - SearchIcon, - SquareIcon, - XCircleIcon, -} from "lucide-react" -import { cn } from "@lib/utils" -import { dmSansClassName } from "@/lib/fonts" -import { - pendingResearchClarification, - type NovaResearchClarificationAnswer, - type NovaResearchEvent, - type NovaResearchRun, -} from "@/lib/nova-research" -import { ResearchClarification } from "./research-clarification" - -function toolLabel(name: string | null, fallback: string | null): string { - if (fallback) return fallback - return (name ?? "Research tool") - .replace(/_/g, " ") - .replace(/\b\w/g, (character) => character.toUpperCase()) -} - -function eventLabel(event: NovaResearchEvent): string | null { - if (event.title === "Research capabilities enabled" && event.message) { - return `Enabled ${event.message} research` - } - if (event.type === "tool") return toolLabel(event.toolName, event.title) - return event.message || event.title -} - -function eventIcon(event: NovaResearchEvent) { - if (event.status === "running" || event.status === "pending") { - return - } - if (event.status === "failed" || event.type === "error") { - return - } - if (event.type === "tool") { - return - } - if (event.type === "assistant") { - return - } - return -} - -function isUsefulTimelineEvent(event: NovaResearchEvent): boolean { - return ( - event.type === "assistant" || - event.type === "tool" || - event.type === "status" || - event.type === "artifact" || - event.type === "error" - ) -} - -export function ResearchProgress({ - run, - onCancel, - onSubmitClarification, - className, -}: { - run: NovaResearchRun - onCancel: () => void - onSubmitClarification: ( - requestId: string, - answers: NovaResearchClarificationAnswer[], - ) => Promise - className?: string -}) { - const active = - run.status === "queued" || - run.status === "running" || - run.status === "awaiting_input" - const failed = run.status === "failed" - const cancelled = run.status === "cancelled" - const awaitingInput = run.status === "awaiting_input" - const [expanded, setExpanded] = useState(true) - const timeline = run.events.filter(isUsefulTimelineEvent) - const clarification = pendingResearchClarification(run) - const statusLabel = awaitingInput - ? "Waiting for your answers" - : active - ? "Researching" - : failed - ? "Research failed" - : cancelled - ? "Research stopped" - : "Research complete" - - return ( -
-
- {awaitingInput ? ( - - ) : active ? ( - - ) : failed ? ( - - ) : ( - - )} - - {active ? ( - - ) : null} -
- {clarification ? ( - - onSubmitClarification(clarification.id, answers) - } - /> - ) : null} - - {expanded && !clarification ? ( -
- {run.plan ? ( -
-
- Plan -
-
- {run.plan.steps.map((step) => ( -
- {step.status === "complete" ? ( - - ) : step.status === "in_progress" ? ( - - ) : ( - - )} - {step.title} -
- ))} -
-
- ) : null} - -
- {timeline.length === 0 ? ( -
- - Preparing the investigation… -
- ) : ( - timeline.map((event) => { - const label = eventLabel(event) - if (!label) return null - return ( -
-
- {eventIcon(event)} -
-
- {label} - {event.type === "tool" && event.toolName ? ( -
- {event.toolName} -
- ) : null} -
-
- ) - }) - )} -
-
- ) : null} -
- ) -}