import { RefreshIcon } from "~/components/ui/refresh-icon"; import { useAtomValue } from "@effect/atom-react"; import { USAGE_CONTRACT_VERSION, type EnvironmentId, type UsageProviderKind, } from "@t3tools/contracts"; import { CircleAlertIcon, ChevronDownIcon, CircleDashedIcon, SlidersHorizontalIcon, } from "lucide-react"; import { useMemo, useRef, useState } from "react"; import { isCompatibleUsageContractVersion, isModelCostUnknown, type DailyTotals, type HourlyTotals, } from "@t3tools/shared/usageMerge"; import { isElectron } from "../../env"; import { cn } from "../../lib/utils"; import { environmentPresentations } from "../../state/presentation"; import { serverEnvironment } from "../../state/server"; import { useUsage, type EnvironmentUsageStatus } from "../../state/usage"; import { useAtomCommand } from "../../state/use-atom-command"; import { enumerateDays, enumerateHourStarts, formatCount, formatDateTimeShort, formatDayShort, formatHourShort, formatPercent, formatTokens, formatUsd, makeWindow, } from "@t3tools/shared/usageFormat"; import { Button } from "../ui/button"; import { Menu, MenuCheckboxItem, MenuItem, MenuPopup, MenuSeparator, MenuTrigger, } from "../ui/menu"; import { ScrollArea } from "../ui/scroll-area"; import { Select, SelectItem, SelectPopup, SelectTrigger, SelectValue } from "../ui/select"; import { SidebarInset } from "../ui/sidebar"; import { Skeleton } from "../ui/skeleton"; import { Toggle, ToggleGroup } from "../ui/toggle-group"; import { WorkspaceBreadcrumb, WorkspaceBreadcrumbItem, WorkspaceBreadcrumbSeparator, } from "../WorkspaceBreadcrumb"; import { WorkspacePageContainer } from "../WorkspacePageContainer"; import { WorkspacePageHeader } from "../WorkspacePageHeader"; import { UsageLimitsSection } from "./UsageLimits"; import { UsagePriceOverrides } from "./UsagePriceOverrides"; import { UsageProviderChart, type UsageChartMetric } from "./UsageProviderChart"; import { PROVIDER_ORDER, PROVIDER_PRESENTATION, providersWithUsage } from "./usageProviders"; import { readUsagePagePreferences, saveUsagePagePreferences, type UsagePagePreferences, } from "./usagePagePreferences"; type UsageMetric = UsageChartMetric | "limits"; const METRIC_OPTIONS = [ { value: "cost", label: "Cost" }, { value: "tokens", label: "Tokens" }, { value: "limits", label: "Limits" }, ] as const satisfies readonly { value: UsageMetric; label: string }[]; function isUsageMetric(value: string | null | undefined): value is UsageMetric { return METRIC_OPTIONS.some((option) => option.value === value); } const WINDOW_OPTIONS = [ { days: 1, label: "Past 24h" }, { days: 7, label: "7 days" }, { days: 30, label: "30 days" }, { days: 90, label: "90 days" }, ] as const; function isUsageWindowDays(value: number): value is UsagePagePreferences["windowDays"] { return WINDOW_OPTIONS.some((option) => option.days === value); } export function UsagePage() { const [preferences, setPreferences] = useState(readUsagePagePreferences); const [windowSelection, setWindowSelection] = useState(() => ({ days: preferences.windowDays, window: makeWindow( preferences.windowDays, undefined, preferences.windowDays === 1 ? "hour" : "day", ), })); const metric = preferences.metric; const showingLimits = metric === "limits"; const [isRefreshing, setIsRefreshing] = useState(false); const refreshingRef = useRef(false); const [breakdown, setBreakdown] = useState<"model" | "time">("model"); const [selectedEnvironmentIds, setSelectedEnvironmentIds] = useState | null>(null); const { days: windowDays, window } = windowSelection; const isPast24Hours = windowDays === 1; const { merged, environments, selectedEnvironments, isPending, isPartial, refresh } = useUsage( window, selectedEnvironmentIds, ); const presentations = useAtomValue(environmentPresentations.presentationsAtom); const refreshProviders = useAtomCommand(serverEnvironment.refreshProviders, { reportFailure: false, }); const days = useMemo( () => enumerateDays(window.sinceDay, window.untilDay), [window.sinceDay, window.untilDay], ); const hours = useMemo( () => window.sinceTime === undefined || window.untilTime === undefined ? [] : enumerateHourStarts(window.sinceTime, window.untilTime), [window.sinceTime, window.untilTime], ); // Newest first: the window can run 90 periods, so the interesting end // belongs at the top of the table. const breakdownPeriods = useMemo( () => (isPast24Hours ? merged.hourly : merged.daily).toReversed(), [isPast24Hours, merged.daily, merged.hourly], ); const breakdownModels = useMemo( () => breakdown === "model" && metric === "tokens" ? merged.models.toSorted( (left, right) => right.totalTokens - left.totalTokens || right.costUsd - left.costUsd, ) : merged.models, [breakdown, merged.models, metric], ); const activeProviders = useMemo(() => providersWithUsage(merged.providers), [merged.providers]); const timeValueColumnWidth = `${60 / (activeProviders.length + 2)}%`; const selectWindow = (days: number) => { if (!isUsageWindowDays(days)) return; const nextPreferences = { metric, windowDays: days }; setPreferences(nextPreferences); saveUsagePagePreferences(nextPreferences); setWindowSelection({ days, window: makeWindow(days, undefined, days === 1 ? "hour" : "day"), }); }; const selectMetric = (nextMetric: UsageMetric) => { const nextPreferences = { metric: nextMetric, windowDays }; setPreferences(nextPreferences); saveUsagePagePreferences(nextPreferences); }; const refreshWindow = () => { if (refreshingRef.current) return; if (showingLimits) { refreshingRef.current = true; setIsRefreshing(true); void Promise.all( Array.from(presentations, ([environmentId, presentation]) => { if (selectedEnvironmentIds !== null && !selectedEnvironmentIds.has(environmentId)) return; if (presentation.connection.phase === "connected" && presentation.serverConfig !== null) { return refreshProviders({ environmentId, input: {} }); } }), ).finally(() => { refreshingRef.current = false; setIsRefreshing(false); }); return; } const nextWindow = makeWindow(windowDays, undefined, isPast24Hours ? "hour" : "day"); if ( nextWindow.sinceDay !== window.sinceDay || nextWindow.untilDay !== window.untilDay || nextWindow.sinceTime !== window.sinceTime || nextWindow.untilTime !== window.untilTime ) { setWindowSelection({ days: windowDays, window: nextWindow }); } refreshingRef.current = true; setIsRefreshing(true); void refresh(nextWindow).finally(() => { refreshingRef.current = false; setIsRefreshing(false); }); }; const windowLabel = isPast24Hours && window.sinceTime !== undefined && window.untilTime !== undefined ? `${formatDateTimeShort(window.sinceTime, window.timeZone)} to ${formatDateTimeShort(window.untilTime, window.timeZone)}` : `${formatDayShort(window.sinceDay)} to ${formatDayShort(window.untilDay)}`; const topbarContent = (

Usage

{!showingLimits ? ( {windowLabel} ) : null}
{ const value = next[0]; if (isUsageMetric(value)) selectMetric(value); }} > {METRIC_OPTIONS.map((option) => ( {option.label} ))} {/* The period does not apply to Limits, so it stays in place but disabled; unmounting it shifted the metric toggle ~300px. */} { const value = next[0]; if (value) selectWindow(Number(value)); }} > {WINDOW_OPTIONS.map((option) => ( {option.label} ))}
); return (
{topbarContent} {selectedEnvironments.length === 0 ? (

{environments.length === 0 ? `Connect an environment to see ${showingLimits ? "limits" : "usage"}.` : `Select an environment to see ${showingLimits ? "limits" : "usage"}.`}

) : showingLimits ? ( ) : isPending ? ( ) : ( <>
{metric === "cost" ? formatUsd(merged.costUsd) : formatTokens(merged.totalTokens)} {metric !== "cost" ? `${formatCount(merged.sessions)} sessions` : merged.costQuality.unpricedShare > 0 ? `${formatCount(merged.sessions)} sessions · API estimate excludes ${formatPercent( merged.costQuality.unpricedShare, )} unpriced records` : `${formatCount(merged.sessions)} sessions · API estimate`}
{activeProviders.map((provider) => { const totals = merged.providers.find((entry) => entry.provider === provider); const share = metric === "cost" ? (totals?.costShare ?? 0) : (totals?.tokenShare ?? 0); const providerSessions = totals?.sessions ?? 0; const sessionLabel = `${formatCount(providerSessions)} ${ providerSessions === 1 ? "session" : "sessions" }`; return (
{PROVIDER_PRESENTATION[provider].label} {sessionLabel} {metric === "cost" ? formatUsd(totals?.costUsd ?? 0) : formatTokens(totals?.totalTokens ?? 0)}
{metric === "cost" ? `${formatPercent(share)} of cost · ${formatTokens(totals?.totalTokens ?? 0)} tokens` : `${formatPercent(share)} of tokens · ${formatUsd(totals?.costUsd ?? 0)}`}
); })}

{isPast24Hours ? "Hourly" : "Daily"}{" "} {metric === "tokens" ? "processed tokens" : "cost"}

Totals

Breakdown

{ const value = next[0]; if (value === "model" || value === "time") setBreakdown(value); }} > {( [ { value: "model", label: "Model" }, { value: "time", label: isPast24Hours ? "Hour" : "Day" }, ] as const ).map((option) => ( {option.label} ))}
{breakdown === "model" ? ( {breakdownModels.length === 0 ? ( ) : ( breakdownModels.map((model) => ( )) )}
Model Cost Share Tokens
No activity in this window.
{model.model} {isModelCostUnknown(model) ? ( Unpriced ) : ( formatUsd(model.costUsd) )} {isModelCostUnknown(model) ? "—" : formatPercent(model.costShare)} {formatTokens(model.totalTokens)}
) : ( {activeProviders.map((provider) => ( ))} {activeProviders.map((provider) => ( ))} {breakdownPeriods.length === 0 ? ( ) : ( breakdownPeriods.map((period) => ( {activeProviders.map((provider) => ( ))} )) )}
{isPast24Hours ? "Hour" : "Day"} {PROVIDER_PRESENTATION[provider].label} Total Tokens
No activity in this window.
{"hourStart" in period ? formatHourShort(period.hourStart, window.timeZone) : formatDayShort(period.day)} {formatUsd(period.byProvider.get(provider)?.costUsd ?? 0)} {formatUsd(period.costUsd)} {formatTokens(period.totalTokens)}
)}
)}
); } /** Brand mark for the harness a row belongs to. */ function ProviderMark({ provider, className, }: { readonly provider: UsageProviderKind; readonly className: string; }) { const Mark = PROVIDER_PRESENTATION[provider].mark; return ; } function Metric({ label, value }: { readonly label: string; readonly value: string }) { return (
{label} {value}
); } /** * Explains failed or incompatible environments and deduplicated transcripts. * Shown inside the environment filter so arriving results do not move the page. */ function UsageCoverageNotice({ environments, duplicateSources, staleEnvironments, }: { readonly environments: readonly EnvironmentUsageStatus[]; readonly duplicateSources: readonly string[]; readonly staleEnvironments: readonly string[]; }) { const failed = environments.filter((environment) => environment.error !== null); const stale = environments.filter((environment) => staleEnvironments.includes(environment.environmentId), ); if (failed.length === 0 && stale.length === 0 && duplicateSources.length === 0) { return null; } return (
{failed.map((environment) => ( {environment.label} could not report usage. ))} {stale.map((environment) => ( {environment.label} runs an older server version and is excluded from totals. ))} {duplicateSources.length > 0 ? ( Counted once across environments sharing a transcript directory:{" "} {duplicateSources.join(", ")} ) : null}
); } /** Environment selection and scan progress share a permanent header control. */ function UsageEnvironmentFilter({ environments, selectedEnvironments, selectedEnvironmentIds, onSelectionChange, showUsageStatus, isPartial, duplicateSources, staleEnvironments, }: { readonly environments: readonly EnvironmentUsageStatus[]; readonly selectedEnvironments: readonly EnvironmentUsageStatus[]; readonly selectedEnvironmentIds: ReadonlySet | null; readonly onSelectionChange: (ids: ReadonlySet | null) => void; readonly showUsageStatus: boolean; readonly isPartial: boolean; readonly duplicateSources: readonly string[]; readonly staleEnvironments: readonly string[]; }) { const [modelPricesOpen, setModelPricesOpen] = useState(false); const allSelected = selectedEnvironmentIds === null; const label = allSelected ? "All environments" : selectedEnvironments.length === 1 ? selectedEnvironments[0]!.label : `${selectedEnvironments.length} environments`; const pendingCount = selectedEnvironments.filter( (environment) => environment.error === null && (environment.isPending || environment.summary === null), ).length; const hasIssue = selectedEnvironments.some((environment) => environment.error !== null) || staleEnvironments.length > 0; return ( <> {label} {showUsageStatus && pendingCount > 0 ? ( <> {pendingCount} {pendingCount === 1 ? "environment" : "environments"} still scanning {isPartial ? "; totals are partial" : ""} ) : showUsageStatus && hasIssue ? ( ) : ( )} onSelectionChange(checked ? null : new Set())} > All environments {environments.map((environment) => { const checked = selectedEnvironmentIds === null || selectedEnvironmentIds.has(environment.environmentId); const status = environment.error !== null ? "Unavailable" : environment.summary !== null && !isCompatibleUsageContractVersion( environment.summary.contractVersion, USAGE_CONTRACT_VERSION, ) ? "Update required" : environment.summary === null ? "Scanning…" : environment.isPending ? "Refreshing…" : "Ready"; return ( { const next = new Set(selectedEnvironments.map((entry) => entry.environmentId)); if (nextChecked) next.add(environment.environmentId); else next.delete(environment.environmentId); onSelectionChange(next.size === environments.length ? null : next); }} > {environment.label} {showUsageStatus ? ( {status} ) : null} ); })} {environments.length === 0 ? (

No environments connected.

) : null} {showUsageStatus && isPartial ? (

Totals are partial while selected environments scan.

) : null} {showUsageStatus ? ( ) : null} setModelPricesOpen(true)}> Model prices
{modelPricesOpen ? ( ) : null} ); } /** * Stand-in with the loaded page's shape, using the shared `Skeleton` bars so it * breathes with the same `animate-skeleton` pulse as every other loading state. * Replaced by results as soon as the first environment answers. */ function UsageSkeleton() { return ( <>
{PROVIDER_ORDER.map((provider) => (
))}

Totals

{["Processed tokens", "Cached input", "Uncached input", "Output", "Cache savings"].map( (label) => (
{label}
), )}

Breakdown

); }