import { useState } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; // --------------------------------------------------------------------------- // TokenMeter — circular SVG gauge showing token usage // Inspired by DeerFlow's token usage display // --------------------------------------------------------------------------- interface TokenMeterProps { inputTokens: number; outputTokens: number; model?: string; className?: string; } // Color thresholds function getUsageColor(percent: number): string { if (percent >= 80) return '#ef4444'; // red if (percent >= 50) return '#eab308'; // yellow return '#22c55e'; // green } // Format token count for display function formatTokens(n: number): string { if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`; if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`; return String(n); } export function TokenMeter({ inputTokens, outputTokens, model, className = '' }: TokenMeterProps) { const [showDetail, setShowDetail] = useState(false); const total = inputTokens + outputTokens; // Assume ~128K context window as budget for percentage calculation const budget = 128_000; const percent = Math.min(100, (total / budget) * 100); const color = getUsageColor(percent); // SVG circular gauge parameters const size = 28; const strokeWidth = 3; const radius = (size - strokeWidth) / 2; const circumference = 2 * Math.PI * radius; const offset = circumference - (percent / 100) * circumference; if (total === 0) return null; return (
{/* Hover detail card */} {showDetail && (
Input {formatTokens(inputTokens)}
Output {formatTokens(outputTokens)}
Total {formatTokens(total)}
{model && (
{model}
)}
)}
); }