{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "components-ai-token-usage",
  "title": "Token Usage",
  "description": "A token usage card showing input/output counts, costs, proportion bar, and an interactive token breakdown with tooltips.",
  "dependencies": [
    "lucide-react",
    "class-variance-authority"
  ],
  "registryDependencies": [
    "card",
    "tooltip",
    "https://odysseyui.com/r/components-ui-badge.json"
  ],
  "files": [
    {
      "path": "registry/components/ai/token-usage/index.tsx",
      "content": "'use client';\n\nimport { ArrowUp, ArrowDown } from 'lucide-react';\nimport { Card, CardContent, CardHeader } from '@/components/ui/card';\nimport { Badge, badgeVariants } from '@/components/odyssey/components/ui/badge';\nimport type { VariantProps } from 'class-variance-authority';\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipProvider,\n  TooltipTrigger,\n} from '@/components/ui/tooltip';\n\ntype BadgeVariant = VariantProps<typeof badgeVariants>['variant'];\n\ntype TokenType = 'default' | 'control' | 'system';\n\ninterface Token {\n  text: string;\n  type: TokenType;\n}\n\nconst tokens: Token[] = [\n  { text: 'Analyze', type: 'default' },\n  { text: 'the', type: 'default' },\n  { text: 'following', type: 'default' },\n  { text: 'dataset', type: 'default' },\n  { text: 'and', type: 'default' },\n  { text: 'return', type: 'default' },\n  { text: '\\\\n\\\\n', type: 'control' },\n  { text: '⊲system▷', type: 'system' },\n  { text: 'a', type: 'default' },\n  { text: 'structured', type: 'default' },\n  { text: 'JSON', type: 'default' },\n  { text: '```', type: 'control' },\n  { text: 'summary', type: 'default' },\n  { text: 'with', type: 'default' },\n  { text: 'insights', type: 'default' },\n  { text: '.', type: 'default' },\n];\n\nconst tokenVariants: Record<TokenType, BadgeVariant> = {\n  default: 'secondary',\n  control: 'orange',\n  system: 'purple',\n};\n\nconst tokenTooltips: Record<TokenType, string> = {\n  default: 'Regular text token',\n  control: 'Control character or code delimiter',\n  system: 'System prompt injection token',\n};\n\nconst fmt = (n: number) => n.toLocaleString();\nconst fmtCost = (n: number) => `$${n.toFixed(4)}`;\n\nconst inputTokens = 4391;\nconst outputTokens = 8456;\nconst inputCost = 0.0132;\nconst outputCost = 0.1267;\nconst model = 'claude-sonnet-4.6';\nconst totalTokens = inputTokens + outputTokens;\nconst totalCost = inputCost + outputCost;\n\nconst inputPct = Math.round((inputTokens / totalTokens) * 100);\nconst outputPct = 100 - inputPct;\n\nexport const TokenUsage = () => {\n  return (\n    <Card className=\"w-full max-w-lg overflow-hidden rounded-xl border border-border bg-card\">\n      {/* Header */}\n      <CardHeader className=\"flex flex-row items-center justify-between px-4 border-b border-border\">\n        <div className=\"flex items-center gap-2\">\n          <div className=\"flex items-center justify-center w-6 h-6 rounded-md bg-muted shrink-0\">\n            <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n              <path\n                d=\"M1 2h10M1 6h10M1 10h6\"\n                stroke=\"currentColor\"\n                strokeWidth=\"1.5\"\n                strokeLinecap=\"round\"\n                className=\"text-muted-foreground\"\n              />\n            </svg>\n          </div>\n          <span className=\"text-sm font-medium text-card-foreground\">\n            Token usage\n          </span>\n        </div>\n        <span className=\"text-[11px] text-muted-foreground bg-muted px-2.5 py-0.5 rounded-full border border-border\">\n          {model}\n        </span>\n      </CardHeader>\n\n      {/* Input / Output stats */}\n      <div className=\"grid grid-cols-2 border-b border-border\">\n        <div className=\"px-5 py-4 border-r border-border\">\n          <div className=\"flex items-center gap-1 text-[10px] font-semibold tracking-widest uppercase text-muted-foreground mb-1.5\">\n            <ArrowUp size={9} /> Input\n          </div>\n          <div className=\"text-[22px] font-medium text-foreground leading-none mb-1\">\n            {fmt(inputTokens)}\n          </div>\n          <div className=\"text-[11px] text-muted-foreground\">\n            {fmtCost(inputCost)}\n          </div>\n        </div>\n\n        <div className=\"px-5 py-4\">\n          <div className=\"flex items-center gap-1 text-[10px] font-semibold tracking-widest uppercase text-muted-foreground mb-1.5\">\n            <ArrowDown size={9} /> Output\n          </div>\n          <div className=\"text-[22px] font-medium text-foreground leading-none mb-1\">\n            {fmt(outputTokens)}\n          </div>\n          <div className=\"text-[11px] text-muted-foreground\">\n            {fmtCost(outputCost)}\n          </div>\n        </div>\n      </div>\n\n      {/* Total + proportion bar */}\n      <div className=\"px-5 py-4 border-b border-border\">\n        <div className=\"flex items-baseline justify-between mb-2.5\">\n          <div className=\"flex items-baseline gap-2.5\">\n            <span className=\"text-[10px] font-semibold tracking-widest uppercase text-muted-foreground\">\n              Total tokens\n            </span>\n            <span className=\"text-xl font-medium text-foreground\">\n              {fmt(totalTokens)}\n            </span>\n          </div>\n          <span className=\"text-[13px] font-medium text-emerald-500\">\n            {fmtCost(totalCost)}\n          </span>\n        </div>\n\n        {/* Bar */}\n        <div className=\"h-1.5 rounded-full overflow-hidden flex gap-px\">\n          <div\n            className=\"bg-violet-600 rounded-full\"\n            style={{ width: `${inputPct}%` }}\n          />\n          <div\n            className=\"bg-sky-500 rounded-full\"\n            style={{ width: `${outputPct}%` }}\n          />\n        </div>\n\n        {/* Legend */}\n        <div className=\"flex gap-3.5 mt-2\">\n          <span className=\"flex items-center gap-1.5 text-[10px] text-muted-foreground\">\n            <span className=\"w-2 h-2 rounded-sm bg-violet-600 inline-block\" />\n            Input {inputPct}%\n          </span>\n          <span className=\"flex items-center gap-1.5 text-[10px] text-muted-foreground\">\n            <span className=\"w-2 h-2 rounded-sm bg-sky-500 inline-block\" />\n            Output {outputPct}%\n          </span>\n        </div>\n      </div>\n\n      {/* Token breakdown */}\n      <div className=\"px-5 pt-4 pb-5\">\n        <div className=\"flex items-center justify-between mb-2.5\">\n          <p className=\"text-[10px] font-semibold tracking-widest uppercase text-muted-foreground\">\n            Token breakdown\n          </p>\n          <div className=\"flex gap-3\">\n            <span className=\"flex items-center gap-1.5 text-[10px] text-muted-foreground\">\n              <span className=\"w-1.5 h-1.5 rounded-sm bg-orange-500 inline-block\" />\n              Special\n            </span>\n            <span className=\"flex items-center gap-1.5 text-[10px] text-muted-foreground\">\n              <span className=\"w-1.5 h-1.5 rounded-sm bg-purple-500 inline-block\" />\n              System\n            </span>\n          </div>\n        </div>\n\n        <TooltipProvider>\n          <div className=\"flex flex-wrap gap-1.5\">\n            {tokens.map((token, i) => (\n              <Tooltip key={i}>\n                <TooltipTrigger asChild>\n                  <Badge\n                    variant={tokenVariants[token.type]}\n                    className=\"cursor-pointer\"\n                  >\n                    {token.text}\n                  </Badge>\n                </TooltipTrigger>\n                <TooltipContent side=\"top\">\n                  {tokenTooltips[token.type]}\n                </TooltipContent>\n              </Tooltip>\n            ))}\n          </div>\n        </TooltipProvider>\n      </div>\n    </Card>\n  );\n};\n",
      "type": "registry:ui",
      "target": "components/odysseyui/token-usage.tsx"
    }
  ],
  "type": "registry:ui"
}