profileShare

rasmusjy / roundtable

Read-only snapshot

No repository description.

main default branch 181 files Expires Sep 13, 2026, 9:06 AM
cost-meter.tsx 1,579 bytes
1 'use client';
2
3 import { Coins } from 'lucide-react';
4 import type { DebateView } from '@/lib/debate-view';
5 import { participantColor } from '@/lib/model-visuals';
6 import { formatTokens, formatUsd } from '@/lib/utils';
7
8 /** Compact running cost meter for the debate header. */
9 export function CostMeter({ view }: { view: DebateView }) {
10 const total = view.totals.costUsd;
11 const modelIndex = new Map(view.participants.map((p, i) => [p.model, i]));
12 const segments = Object.entries(view.totals.costByModel)
13 .filter(([, c]) => c > 0)
14 .sort((a, b) => b[1] - a[1]);
15 const max = total || 1;
16
17 return (
18 <div className="rounded-lg border bg-card px-3 py-2">
19 <div className="flex items-center justify-between gap-4">
20 <div className="flex items-center gap-1.5 text-sm font-semibold">
21 <Coins className="h-4 w-4 text-primary" />
22 {formatUsd(total)}
23 </div>
24 <div className="text-[11px] text-muted-foreground">
25 {formatTokens(view.totals.promptTokens + view.totals.completionTokens)} tokens
26 </div>
27 </div>
28 {segments.length > 0 && (
29 <div className="mt-2 flex h-1.5 w-full overflow-hidden rounded-full bg-muted">
30 {segments.map(([model, cost]) => (
31 <div
32 key={model}
33 title={`${model}: ${formatUsd(cost)}`}
34 style={{
35 width: `${(cost / max) * 100}%`,
36 backgroundColor: participantColor(modelIndex.get(model) ?? 5),
37 }}
38 />
39 ))}
40 </div>
41 )}
42 </div>
43 );
44 }
45