fix: token tracking pipeline + premium usage dashboard redesign
Backend fixes: - Fix totalTokens defaulting to 0 when API omits totalTokenCount (now computes prompt+completion) - Fix streaming metadata extraction: unwrap response wrapper in Anthropic/Gemini handlers - Fix Zod schemas: handle SQL SUM(null) with nullable().transform() - Add is_estimated column migration to token_usage table Frontend redesign: - Rewrite Usage page with area charts (nivo/line), horizontal bar model ranking - StatCard: add trend indicators (% vs previous period) and inline SVG sparklines - Premium color palette, prompt/completion ratio bar, top models mini-list - Live indicator with 15s auto-refresh Design system migration: - Standardize all components on Gemini Nexus tokens (rounded-xl, border-white/[0.06]) - Refine UI components, proxy tabs, cloud account list, provider groups
This commit is contained in:
1 parent
b1c76f3b69
commit
a648f2a281
44 files changed
+8920
-14566
No files matched your search
@@ -1,17 +1,21 @@
|
||||
export const COLOR_PROMPT = 'var(--chart-2)';
|
||||
export const COLOR_COMPLETION = 'var(--chart-1)';
|
||||
export const COLOR_TOTAL = 'var(--chart-3)';
|
||||
/** Premium chart palette — refined for dark mode contrast */
|
||||
export const COLOR_PROMPT = '#60a5fa'; // blue-400
|
||||
export const COLOR_COMPLETION = '#34d399'; // emerald-400
|
||||
export const COLOR_TOTAL = '#fbbf24'; // amber-400
|
||||
|
||||
export const PIE_COLORS = [
|
||||
'var(--chart-1)',
|
||||
'var(--chart-2)',
|
||||
'var(--chart-3)',
|
||||
'var(--chart-4)',
|
||||
'var(--chart-5)',
|
||||
'var(--chart-1)',
|
||||
'var(--chart-2)',
|
||||
'var(--chart-3)',
|
||||
'#60a5fa', '#34d399', '#fbbf24', '#a78bfa', '#f472b6',
|
||||
'#38bdf8', '#4ade80', '#facc15', '#c084fc',
|
||||
];
|
||||
|
||||
export const MODEL_COLORS: Record<string, string> = {
|
||||
'gemini-3-flash': '#60a5fa',
|
||||
'gemini-3.1-pro-low': '#818cf8',
|
||||
'gemini-3.1-pro-high': '#a78bfa',
|
||||
'claude-sonnet-4-6-thinking': '#f472b6',
|
||||
'claude-opus-4-6-thinking': '#fb7185',
|
||||
};
|
||||
|
||||
const colorMap: Record<string, string> = {
|
||||
Prompt: COLOR_PROMPT,
|
||||
Completion: COLOR_COMPLETION,
|
||||
@@ -22,7 +26,7 @@ export function BarTooltip({ indexValue, data }: any) {
|
||||
const keys = Object.keys(data).filter((k: string) => k !== 'name' && colorMap[k]);
|
||||
|
||||
return (
|
||||
<div className="bg-popover border-border rounded-md border px-3 py-2 shadow-md">
|
||||
<div className="bg-popover rounded-lg border border-white/[0.06] px-3 py-2 shadow-md">
|
||||
<p className="text-foreground mb-1.5 text-xs font-medium">{indexValue}</p>
|
||||
<div className="flex flex-col gap-1">
|
||||
{keys.map((key: string) => (
|
||||
@@ -44,7 +48,7 @@ export function BarTooltip({ indexValue, data }: any) {
|
||||
|
||||
export function PieTooltip({ datum }: any) {
|
||||
return (
|
||||
<div className="bg-popover border-border rounded-md border px-3 py-2 shadow-md">
|
||||
<div className="bg-popover rounded-lg border border-white/[0.06] px-3 py-2 shadow-md">
|
||||
<div className="flex items-center gap-2 text-xs">
|
||||
<span
|
||||
className="h-2 w-2 rounded-full"
|
||||
@@ -58,3 +62,21 @@ export function PieTooltip({ datum }: any) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function LineTooltip({ point }: any) {
|
||||
return (
|
||||
<div className="bg-popover rounded-lg border border-white/[0.06] px-3 py-2 shadow-md">
|
||||
<p className="text-foreground mb-1 text-xs font-medium">{point.data.xFormatted ?? point.data.x}</p>
|
||||
<div className="flex items-center gap-2 text-xs">
|
||||
<span
|
||||
className="h-2 w-2 rounded-full"
|
||||
style={{ backgroundColor: point.serieColor }}
|
||||
/>
|
||||
<span className="text-muted-foreground">{point.serieId}:</span>
|
||||
<span className="text-foreground font-mono font-medium">
|
||||
{typeof point.data.y === 'number' ? point.data.y.toLocaleString() : point.data.y}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user