{ "name": "prompt-versions", "type": "registry:ui", "title": "Prompt Versions", "description": "A prompt’s history with what each change did to the score. The pairing is the point: a history without outcomes says what happened, a score chart without edits says something changed, and neither answers which edit made it worse.", "category": "Prompts", "dependencies": [ "lucide-react@^1.39.0" ], "registryDependencies": [ "badge", "button", "lib-motion", "lib-styles", "lib-utils" ], "files": [ { "path": "components/ui/prompt-versions.tsx", "type": "registry:ui", "content": "import type { ComponentProps, ReactNode } from 'react'\nimport { GitBranch, TrendingDown, TrendingUp } from 'lucide-react'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { enterFade } from '@/lib/motion'\nimport { focusRing, radius, surface } from '@/lib/styles'\nimport { cn } from '@/lib/utils'\n\n/**\n * A prompt's version history, with what each change did to the score.\n *\n * The pairing that makes this useful: a version and its eval result on the same\n * row. A history that lists edits without outcomes tells you what happened; a\n * dashboard that shows scores without the edits tells you something changed.\n * Neither answers \"which edit made it worse\", which is the only question anyone\n * opens this for.\n *\n * **Deltas are against the previous version, not against the best.** Regression\n * hunting walks backwards one step at a time, and a delta against a distant\n * high-water mark makes every version after it look equally bad.\n *\n * The live version is marked rather than sorted to the top — its position in\n * the sequence is information, and moving it hides how many versions have\n * shipped since.\n */\nexport type PromptVersion = {\n id: string\n /** A label, tag or hash — whatever you version by. */\n label: string\n /** Already formatted — this component does not own your locale. */\n at?: string\n author?: string\n /** One line on what changed. */\n note?: ReactNode\n /** Eval score, 0–1. Omit for a version that was never scored. */\n score?: number\n /** Currently deployed. */\n live?: boolean\n}\n\ntype PromptVersionsProps = Omit, 'onSelect'> & {\n /** Newest first. Order is preserved — position carries meaning. */\n versions: PromptVersion[]\n selectedId?: string\n onSelect?: (version: PromptVersion) => void\n /** Compare two versions — usually opens a PromptDiff. */\n onCompare?: (a: PromptVersion, b: PromptVersion) => void\n compareLabel?: string\n liveLabel?: string\n unscoredLabel?: string\n emptyLabel?: string\n formatScore?: (score: number) => string\n label?: string\n}\n\nfunction PromptVersions({\n versions,\n selectedId,\n onSelect,\n onCompare,\n compareLabel = 'Diff',\n liveLabel = 'Live',\n unscoredLabel = 'not scored',\n emptyLabel = 'No versions yet.',\n formatScore = (score) => `${Math.round(score * 100)}%`,\n label = 'Versions',\n className,\n ...props\n}: PromptVersionsProps) {\n if (versions.length === 0) {\n return (\n
\n

{emptyLabel}

\n
\n )\n }\n\n return (\n \n

\n {label}\n

\n\n \n \n )\n}\n\nexport { PromptVersions }\nexport type { PromptVersionsProps }\n" } ] }