"use client" import { useMemo, useState } from "react" import { Copy, ExternalLink, FileSearch, Flag, GitPullRequestArrow, MessageSquare, } from "lucide-react" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Button } from "@/components/ui/button" interface FlagScoreButtonProps { modelName: string modelId: string benchmarkName: string benchmarkId?: string score: number | string /** URL to the published source the score was extracted from (paper, blog, leaderboard). */ sourceUrl?: string /** URL to the processed record JSON in the card_backend HF dataset. */ sourceRecordUrl?: string /** Optional explicit upstream record URL in evaleval/EEE_datastore (raw source of truth). */ eeeRecordUrl?: string } interface DatasetLinks { repoSlug: string recordViewUrl: string | null recordRawUrl: string | null discussionsUrl: string newDiscussionUrl: string } /** * Given a /resolve/main/... HF dataset URL, derive the helpful sibling URLs * for the dataset (file viewer, discussions list, new-discussion form). Returns * null when the input doesn't look like a HF dataset URL. */ function deriveDatasetLinks(recordUrl: string | undefined, prefilledTitle: string): DatasetLinks | null { if (!recordUrl) return null const m = recordUrl.match( /^https:\/\/huggingface\.co\/datasets\/([^/]+\/[^/]+)\/(?:resolve|raw|blob)\/[^/]+\/(.*)$/, ) if (!m) return null const repoSlug = m[1] const path = m[2] const datasetBase = `https://huggingface.co/datasets/${repoSlug}` const recordViewUrl = `${datasetBase}/blob/main/${path}` const recordRawUrl = `${datasetBase}/resolve/main/${path}` const discussionsUrl = `${datasetBase}/discussions` const newDiscussionUrl = `${datasetBase}/discussions/new?title=${encodeURIComponent(prefilledTitle)}` return { repoSlug, recordViewUrl, recordRawUrl, discussionsUrl, newDiscussionUrl } } /** * "Flag this score" — researcher affordance that, instead of capturing the * report ourselves, sends the user directly to the upstream HF dataset where * the data lives. They can then file a discussion or submit a correction PR * against the actual record. We also offer a copyable context snippet so the * issue body has all the relevant identifiers without needing to retype them. */ export function FlagScoreButton({ modelName, modelId, benchmarkName, benchmarkId, score, sourceUrl, sourceRecordUrl, eeeRecordUrl, }: FlagScoreButtonProps) { const [open, setOpen] = useState(false) const [copied, setCopied] = useState<"context" | null>(null) const prefilledTitle = `Possible issue: ${modelName} on ${benchmarkName} (score ${score})` const cardBackendLinks = useMemo( () => deriveDatasetLinks(sourceRecordUrl, prefilledTitle), [sourceRecordUrl, prefilledTitle], ) const eeeLinks = useMemo( () => deriveDatasetLinks(eeeRecordUrl, prefilledTitle), [eeeRecordUrl, prefilledTitle], ) // Prefer the EEE upstream as the "correction venue" when known — that's // where raw evaluation records live. Fall back to card_backend (the // pipeline output) when EEE isn't directly addressable for this row. const correctionLinks = eeeLinks ?? cardBackendLinks const contextSnippet = [ `Model: ${modelName} (${modelId})`, `Benchmark: ${benchmarkName}${benchmarkId ? ` (${benchmarkId})` : ""}`, `Reported score: ${score}`, sourceUrl ? `Original source URL: ${sourceUrl}` : null, sourceRecordUrl ? `Pipeline record: ${sourceRecordUrl}` : null, eeeRecordUrl ? `EEE upstream record: ${eeeRecordUrl}` : null, ] .filter(Boolean) .join("\n") const handleCopyContext = async () => { try { await navigator.clipboard.writeText(contextSnippet) setCopied("context") setTimeout(() => setCopied(null), 1800) } catch { // Clipboard might be blocked; ignore — the user can still select text manually. } } return ( <> setOpen(true)} > Flag this score Flag this score Take this report directly to the dataset where the record lives. You can file a discussion or open a correction PR against the actual file. Flagging {modelName}{" "} on{" "} {benchmarkName} Score: {score} {correctionLinks?.recordViewUrl && ( View the underlying record Opens the JSON file on{" "} {correctionLinks.repoSlug} )} {correctionLinks && ( Open a discussion Pre-filled title; paste the context snippet into the body. )} {correctionLinks && ( Browse existing discussions Check whether someone already filed a similar correction. )} {!correctionLinks && ( No upstream record URL is recorded for this row, so we can't link directly to the dataset. Copy the context below and file an issue at{" "} evaleval/EEE_datastore/discussions . )} Context to paste into the issue {copied === "context" ? "Copied" : "Copy"} {contextSnippet} setOpen(false)}> Close > ) }
{contextSnippet}