"use client"; import { useId, useState } from "react"; import { FileTextIcon, Loader2Icon } from "lucide-react"; import { Markdown } from "yt-dlp-transcript-common/components/Markdown"; import type { RetrievedVideo } from "../lib/askRetrieval"; import { CitationSources, linkifyCitations, makeCitationLink } from "./citations"; // The running "report" surface for report mode: a persistent markdown document // the model maintains via the update_report tool while the user keeps chatting. // The header carries the on/off toggle (disabled on transports without native // tools, since there is no tool to write the report), a live "updating…" shimmer // while a turn is writing, and the rendered report (or an empty-state hint). // Collapsible like the Context panel so it stays out of the way until wanted. export function ReportPanel({ report, sources, onOpenCitation, reportMode, setReportMode, available, updating, busy, sweeping = false, }: { report: string; // The report's source registry — what its `[n]` / `[n @ mm:ss]` citations index // into. Drives the clickable citations + the numbered Sources list below. sources: RetrievedVideo[]; // Open the transcript modal seeked to a cited line. Undefined in hub /ask (no // player), where citations fall back to scroll-to-source within the list below. onOpenCitation?: (slug: string, seconds?: number) => void; reportMode: boolean; setReportMode: (on: boolean) => void; available: boolean; updating: boolean; busy: boolean; // A whole-corpus sweep is folding batches into the report — force the panel // open so its document is visibly growing, and keep the "updating" shimmer on. sweeping?: boolean; }) { const [open, setOpen] = useState(false); // Stable per-panel id so the report's citation anchors don't collide with a // chat message's. const cid = useId().replace(/:/g, ""); const CitationLink = makeCitationLink(cid, sources, onOpenCitation); const hasReport = report.trim() !== ""; // While a sweep runs, keep the panel expanded (so its document is visibly // growing) regardless of the user's toggle. const expanded = open || sweeping; const busyWriting = updating || sweeping; return (
setOpen((e.currentTarget as HTMLDetailsElement).open)} > Report {busyWriting && ( updating… )} {/* The toggle lives in the header so it's reachable without expanding. */} {expanded && (
{!available && (

Report mode needs a tool-capable provider. Switch the search mode off Scripted (Auto or Native tools) to enable it.

)} {hasReport ? (
{linkifyCitations(report, sources.length, cid)} {sources.length > 0 && (

Sources

)}
) : (

Turn on report mode and ask a question — the assistant will build a report here, keeping it current as the conversation grows.

)}
)}
); }