import { type ReactNode, useEffect, useMemo, useState } from 'react'; import { Alert, Box, Button, CircularProgress, Divider, Link, Popover, Tooltip, Typography, } from '@mui/material'; import PaidOutlinedIcon from '@mui/icons-material/PaidOutlined'; import OpenInNewIcon from '@mui/icons-material/OpenInNew'; import { useSessionStore } from '@/store/sessionStore'; import { type HfAccountUsageBucket, type HfInferenceProvidersCredits, type UsageBucket, useUsageStore, } from '@/store/usageStore'; function formatUsd(value: number | undefined): string { const amount = value ?? 0; if (amount > 0 && amount < 0.01) return '<$0.01'; return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 2, maximumFractionDigits: 2, }).format(amount); } function formatCount(value: number | undefined): string { return new Intl.NumberFormat('en-US').format(value ?? 0); } function contextTokenCount(telemetry: UsageBucket | null | undefined): number | undefined { if (!telemetry) return undefined; if (telemetry.total_tokens > 0) { return Math.max(0, telemetry.total_tokens - telemetry.completion_tokens); } return ( telemetry.prompt_tokens + telemetry.cache_read_tokens + telemetry.cache_creation_tokens ); } function billingUnavailableMessage(error: string | null | undefined): string | null { if (!error) return null; if (error === 'missing_hf_token') return 'Sign in to view HF account billing usage.'; if (error === 'billing_usage_unavailable') { return 'HF billing usage is unavailable. Showing app-observed calls and tokens; inference cost may be incomplete.'; } return 'HF billing usage is unavailable. Showing app-observed calls and tokens; inference cost may be incomplete.'; } function UsageRow({ label, value, strong = false, }: { label: string; value: string; strong?: boolean; }) { return ( <> {label} {value} ); } function UsageGrid({ children }: { children: ReactNode }) { return ( {children} ); } function AccountUsageSection({ title, account, telemetry, }: { title: string; account: HfAccountUsageBucket | null | undefined; telemetry: UsageBucket | null | undefined; }) { const useJobEstimate = !account || (account.hf_jobs_usd <= 0 && (telemetry?.hf_jobs_estimated_usd ?? 0) > 0); return ( {title} ); } function CreditsSection({ credits }: { credits: HfInferenceProvidersCredits | null | undefined }) { if (!credits) return null; return ( <> Inference credits {credits.limit_usd > 0 && ( )} ); } export default function UsageMeter() { const activeSessionId = useSessionStore((state) => state.activeSessionId); const activeSessionYoloSpend = useSessionStore((state) => { const active = state.sessions.find((session) => session.id === state.activeSessionId); return active?.autoApprovalEstimatedSpendUsd ?? null; }); const { usage, isLoading, error, fetchUsage } = useUsageStore(); const [anchorEl, setAnchorEl] = useState(null); useEffect(() => { void fetchUsage(activeSessionId); }, [activeSessionId, activeSessionYoloSpend, fetchUsage]); const accountSessionInference = usage?.hf_account?.current_session?.inference_providers_usd; const sessionTotal = accountSessionInference == null ? usage?.session?.total_usd : accountSessionInference + (usage?.session?.hf_jobs_estimated_usd ?? 0) + (usage?.session?.sandbox_estimated_usd ?? 0); const links = useMemo(() => usage?.links ?? {}, [usage?.links]); const billingMessage = billingUnavailableMessage(usage?.hf_account?.error); const open = Boolean(anchorEl); return ( <> setAnchorEl(null)} anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} transformOrigin={{ vertical: 'top', horizontal: 'right' }} slotProps={{ paper: { sx: { width: 320, maxWidth: 'calc(100vw - 24px)', maxHeight: 'calc(100vh - 24px)', overflowY: 'auto', p: 2, border: '1px solid', borderColor: 'divider', }, }, }} > Usage Estimated from HF account usage per session. {error ? ( {error} ) : ( <> {billingMessage && ( {billingMessage} )} )} {links.hf_billing && ( HF billing )} {links.jobs_pricing && ( Jobs pricing )} ); }