-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Expand file tree
/
Copy pathContextWindowMeter.tsx
More file actions
76 lines (73 loc) · 2.71 KB
/
ContextWindowMeter.tsx
File metadata and controls
76 lines (73 loc) · 2.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import { cn } from "~/lib/utils";
import { type ContextWindowSnapshot, formatContextWindowTokens } from "~/lib/contextWindow";
function formatPercentage(value: number | null): string | null {
if (value === null || !Number.isFinite(value)) {
return null;
}
if (value < 10) {
return `${value.toFixed(1).replace(/\.0$/, "")}%`;
}
return `${Math.round(value)}%`;
}
export function ContextWindowMeter(props: {
usage: ContextWindowSnapshot;
onOpenContextTab: () => void;
}) {
const { usage, onOpenContextTab } = props;
const usedPercentage = formatPercentage(usage.usedPercentage);
const normalizedPercentage = Math.max(0, Math.min(100, usage.usedPercentage ?? 0));
const radius = 9.75;
const circumference = 2 * Math.PI * radius;
const dashOffset = circumference - (normalizedPercentage / 100) * circumference;
return (
<button
type="button"
onClick={onOpenContextTab}
className="group/meter inline-flex cursor-pointer items-center justify-center rounded-full p-1 transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background"
aria-label={
usage.maxTokens !== null && usedPercentage
? `Context window ${usedPercentage} used`
: `Context window ${formatContextWindowTokens(usage.usedTokens)} tokens used`
}
>
<span className="relative flex h-6 w-6 items-center justify-center">
<svg
viewBox="0 0 24 24"
className="-rotate-90 absolute inset-0 h-full w-full transform-gpu"
aria-hidden="true"
>
<circle
cx="12"
cy="12"
r={radius}
fill="none"
stroke="color-mix(in oklab, var(--color-muted) 70%, transparent)"
strokeWidth="3"
/>
<circle
cx="12"
cy="12"
r={radius}
fill="none"
stroke="var(--color-muted-foreground)"
strokeWidth="3"
strokeLinecap="round"
strokeDasharray={circumference}
strokeDashoffset={dashOffset}
className="transition-[stroke-dashoffset] duration-500 ease-out motion-reduce:transition-none"
/>
</svg>
<span
className={cn(
"relative flex h-3.75 w-3.75 items-center justify-center rounded-full bg-background text-[8px] font-medium transition-colors group-hover/meter:bg-accent",
"text-muted-foreground",
)}
>
{usage.usedPercentage !== null
? Math.round(usage.usedPercentage)
: formatContextWindowTokens(usage.usedTokens)}
</span>
</span>
</button>
);
}