import { type EnvironmentId, type ProviderConsumeResetCreditOutcome, ProviderInstanceId, ServerProvider, ServerProviderResetCredits, ServerProviderUsageWindow, UsageLimitSourceAccount, UsageLimitSourceSnapshot, UsageProviderKind,} from "@t3tools/contracts";import { useAtomValue } from "@effect/atom-react";import { collectLimitSources, collectLimitsGroups, elapsedShare, formatDuration, formatResetsIn, limitsNotice, type LimitPace, paceOf, providerLimitsLabel,} from "@t3tools/shared/usageLimits";import { GaugeIcon, TrendingDownIcon, TrendingUpIcon } from "lucide-react";import { Fragment, useState } from "react"; import { usePrimarySettings } from "../../hooks/useSettings";import { environmentPresentations } from "../../state/presentation";import { serverEnvironment } from "../../state/server";import { useAtomCommand } from "../../state/use-atom-command";import { formatUpcomingTimestamp } from "../../timestampFormat";import { ProviderInstanceIcon } from "../chat/ProviderInstanceIcon";import { getDriverOption } from "../settings/providerDriverMeta";import { RedactedSensitiveText } from "../settings/RedactedSensitiveText";import { AlertDialog, AlertDialogClose, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPopup, AlertDialogTitle,} from "../ui/alert-dialog";import { Button } from "../ui/button";import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";import { PROVIDER_PRESENTATION } from "./usageProviders"; const PACE: Record<LimitPace, { readonly label: string; readonly icon: typeof GaugeIcon }> = { ahead: { label: "Ahead of pace: spending faster than the window elapses", icon: TrendingUpIcon }, on: { label: "On pace with the window", icon: GaugeIcon }, under: { label: "Under pace: headroom left for the rest of the window", icon: TrendingDownIcon },}; /** The series colour the cost chart uses for this driver, so the two views read as one. */function barColor(driver: ServerProvider["driver"]): string { const kind: UsageProviderKind | undefined = driver === "codex" ? "codex" : driver === "claudeAgent" ? "claude" : undefined; return kind ? PROVIDER_PRESENTATION[kind].color : "var(--foreground)";} /** Pace as a glyph with the words on hover. */function PaceIcon({ pace }: { readonly pace: LimitPace }) { const Icon = PACE[pace].icon; return ( <Tooltip> <TooltipTrigger render={ <span role="img" aria-label={PACE[pace].label} className="inline-flex text-muted-foreground" /> } > <Icon className="size-3.5" aria-hidden /> </TooltipTrigger> <TooltipPopup side="top">{PACE[pace].label}</TooltipPopup> </Tooltip> );} /** * One window as a full-width bar from the moment it opened to its reset. * The fill is the share of quota spent; the hairline is how far into the * window the clock is, which is also where even spending would have put the * fill. Hover for the exact figures and reset time. */function WindowBar({ color, window, now,}: { readonly color: string; readonly window: ServerProviderUsageWindow; readonly now: number;}) { const timestampFormat = usePrimarySettings((settings) => settings.timestampFormat); const used = Math.max(0, Math.min(100, window.usedPercent)); const elapsed = elapsedShare(window, now); const resetsIn = formatResetsIn(window, now); const resetsAt = window.resetsAt ? formatUpcomingTimestamp(window.resetsAt, timestampFormat, now) : null; const summary = `${window.label}: ${Math.round(used)}% used${ elapsed === null ? "" : `, ${Math.round(elapsed * 100)}% of the window elapsed` }${resetsIn ? `, ${resetsIn}` : ""}`; return ( <Tooltip> <TooltipTrigger render={ <div role="img" aria-label={summary} tabIndex={0} className="relative h-6 cursor-default rounded-full outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background" /> } > <div className="absolute inset-x-0 inset-y-1.5 rounded-full bg-muted" /> {used > 0 ? ( <div className="absolute inset-y-1.5 left-0 rounded-full" style={{ width: `${used}%`, backgroundColor: color }} /> ) : null} {elapsed !== null ? ( <span aria-hidden className="absolute inset-y-0.5 w-px -translate-x-1/2 bg-foreground/60" style={{ left: `${elapsed * 100}%` }} /> ) : null} </TooltipTrigger> <TooltipPopup side="top" className="max-w-72 text-xs"> <div className="flex flex-col gap-0.5"> <span className="text-foreground"> {Math.round(used)}% used {elapsed !== null ? ` · ${Math.round(elapsed * 100)}% of the window elapsed` : ""} </span> {elapsed !== null ? ( <span className="text-muted-foreground">The line is where even spending would be.</span> ) : null} {resetsAt ? ( <span className="text-muted-foreground"> Resets {resetsAt} {resetsIn ? ` · ${resetsIn}` : ""} </span> ) : null} </div> </TooltipPopup> </Tooltip> );} /** One account's windows as rows: label and percent, bar, pace and countdown. */function LimitWindows({ driver, windows, now,}: { readonly driver: ServerProvider["driver"]; readonly windows: ReadonlyArray<ServerProviderUsageWindow>; readonly now: number;}) { const color = barColor(driver); return ( <div className="grid grid-cols-[11rem_minmax(0,1fr)_7rem] gap-x-4 gap-y-1"> {windows.map((window, index) => { // Windows that reset together show the countdown once. const previous = windows[index - 1]; const sharesReset = previous?.resetsAt !== undefined && previous.resetsAt === window.resetsAt; const pace = paceOf(window, now); const resetsIn = formatResetsIn(window, now); return ( <Fragment key={window.id}> <span className="flex min-w-0 items-center gap-2 text-xs"> <span className="truncate text-muted-foreground">{window.label}</span> <span className="ms-auto shrink-0 font-medium text-foreground tabular-nums"> {Math.round(window.usedPercent)}% </span> </span> <WindowBar color={color} window={window} now={now} /> <span className="flex items-center gap-2 text-xs text-muted-foreground tabular-nums"> {pace ? <PaceIcon pace={pace} /> : null} <span className="ms-auto shrink-0">{sharesReset ? "" : (resetsIn ?? "")}</span> </span> </Fragment> ); })} </div> );} /** * Heading shared by local providers and source accounts: icon, driver, instance, plan, * and the signed-in email blurred until clicked, as provider settings do. */function AccountHeading({ driver, label, instanceLabel, plan, email, accentColor,}: { readonly driver: ServerProvider["driver"]; readonly label: string; readonly instanceLabel: string; readonly plan: string | undefined; readonly email: string | undefined; readonly accentColor?: string | undefined;}) { return ( <h2 className="flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 text-sm font-medium text-foreground"> <ProviderInstanceIcon driverKind={driver} displayName={instanceLabel} accentColor={accentColor} showBadge={Boolean(accentColor)} indicatorBackground="var(--background)" className="size-5" iconClassName="size-4 text-foreground/80" /> <span className="truncate">{label}</span> {instanceLabel !== label ? ( <span className="min-w-0 truncate text-xs font-normal text-muted-foreground"> · {instanceLabel} </span> ) : null} {plan ? <span className="font-normal text-muted-foreground">· {plan}</span> : null} {email ? ( <RedactedSensitiveText value={email} ariaLabel="Toggle account email visibility" revealTooltip="Click to reveal email" hideTooltip="Click to hide email" /> ) : null} </h2> );} function ProviderLimits({ provider, environmentId, now,}: { readonly provider: ServerProvider; readonly environmentId: EnvironmentId; readonly now: number;}) { const limits = provider.usageLimits; if (!limits) return null; const notice = limitsNotice(limits); return ( <section className="flex flex-col gap-3"> <AccountHeading driver={provider.driver} label={getDriverOption(provider.driver)?.label ?? String(provider.driver)} instanceLabel={providerLimitsLabel(provider, (driver) => getDriverOption(driver)?.label)} plan={provider.auth.label} email={provider.auth.email} accentColor={provider.accentColor} /> {notice ? ( <span className="text-xs text-muted-foreground">{notice}</span> ) : ( <LimitWindows driver={provider.driver} windows={limits.windows} now={now} /> )} {limits.resetCredits ? ( <ResetCredits environmentId={environmentId} instanceId={provider.instanceId} credits={limits.resetCredits} now={now} /> ) : null} </section> );} const OUTCOME_TEXT: Record<ProviderConsumeResetCreditOutcome, string> = { reset: "Reset applied. Your windows have cleared.", nothingToReset: "Nothing to reset right now.", noCredit: "No reset credit left.", alreadyRedeemed: "That credit was already redeemed.",}; /** * Banked reset credits with a confirmed redeem action. Redeeming spends a * credit the provider granted the user, so it never fires on a bare click. */function ResetCredits({ environmentId, instanceId, credits, now,}: { readonly environmentId: EnvironmentId; readonly instanceId: ProviderInstanceId; readonly credits: ServerProviderResetCredits; readonly now: number;}) { const consume = useAtomCommand(serverEnvironment.consumeResetCredit, { reportFailure: false }); const [confirming, setConfirming] = useState(false); const [busy, setBusy] = useState(false); const [status, setStatus] = useState<string | null>(null); if (credits.availableCount === 0 && status === null) return null; const expiresIn = credits.nextExpiresAt ? formatDuration(Date.parse(credits.nextExpiresAt) - now) : null; const summary = credits.availableCount === 0 ? "No reset credits banked" : `${credits.availableCount} ${credits.availableCount === 1 ? "reset credit" : "reset credits"} banked${ expiresIn ? ` · next expires in ${expiresIn}` : "" }`; const redeem = async () => { setConfirming(false); setBusy(true); setStatus(null); const result = await consume({ environmentId, input: { instanceId } }); setBusy(false); if (result._tag === "Success") { setStatus(OUTCOME_TEXT[result.value.outcome]); return; } setStatus( "error" in result.cause && result.cause.error instanceof Error ? result.cause.error.message : "Could not use the reset credit.", ); }; return ( <div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground"> <span className="tabular-nums">{summary}</span> {credits.availableCount > 0 ? ( <Button size="xs" variant="outline" disabled={busy} onClick={() => setConfirming(true)}> {busy ? "Using credit…" : "Use a reset credit"} </Button> ) : null} {status ? <span className="text-foreground">{status}</span> : null} <AlertDialog open={confirming} onOpenChange={setConfirming}> <AlertDialogPopup> <AlertDialogHeader> <AlertDialogTitle>Use a reset credit?</AlertDialogTitle> <AlertDialogDescription> This redeems one credit on your account and clears the current rate-limit windows. It cannot be undone. </AlertDialogDescription> </AlertDialogHeader> <AlertDialogFooter> <AlertDialogClose render={<Button variant="outline" />}>Cancel</AlertDialogClose> <Button onClick={() => void redeem()}>Use credit</Button> </AlertDialogFooter> </AlertDialogPopup> </AlertDialog> </div> );} /** One account pooled by a usage-limit source, drawn like a provider row. */function SourceAccountLimits({ account, sourceKind, now,}: { readonly account: UsageLimitSourceAccount; readonly sourceKind: string; readonly now: number;}) { const notice = limitsNotice(account.usageLimits); return ( <section className="flex flex-col gap-3"> <AccountHeading driver={account.driver} label={getDriverOption(account.driver)?.label ?? String(account.driver)} instanceLabel={sourceKind} plan={account.plan} email={account.email} /> {notice ? ( <span className="text-xs text-muted-foreground">{notice}</span> ) : ( <LimitWindows driver={account.driver} windows={account.usageLimits.windows} now={now} /> )} </section> );} const SOURCE_KIND_LABEL: Record<UsageLimitSourceSnapshot["kind"], string> = { cliproxy: "CLI Proxy",}; type LimitsSource = ReturnType<typeof collectLimitSources>[number]; /** Read-only accounts pooled by a configured usage source. */function SourceLimits({ source, now }: { readonly source: LimitsSource; readonly now: number }) { const kind = SOURCE_KIND_LABEL[source.kind]; return ( <div className="flex flex-col gap-6"> {source.error ? ( <span className="text-xs text-muted-foreground">{source.error}</span> ) : source.accounts.length === 0 ? ( <span className="text-xs text-muted-foreground"> {source.hiddenAccountCount > 0 ? "All accounts are shown by connected providers." : "No accounts reported."} </span> ) : ( source.accounts.map((account) => ( <SourceAccountLimits key={account.id} account={account} sourceKind={kind} now={now} /> )) )} </div> );} /** * Subscription quota windows from every connected environment's providers. * Countdowns anchor to render time rather than ticking: a live clock would * repaint the page every minute for no decision-changing gain. */export function UsageLimitsSection() { const presentations = useAtomValue(environmentPresentations.presentationsAtom); const groups = collectLimitsGroups(presentations); const sources = collectLimitSources(presentations); // Anchored once per mount on purpose: countdowns must not tick (see below). const [now] = useState(() => Date.now()); return ( <div className="flex flex-col gap-8"> {groups.length === 0 && sources.length === 0 ? ( <p className="text-sm text-muted-foreground"> No provider on a connected environment reports subscription limits. </p> ) : null} {sources.map((source) => ( <SourceLimits key={source.key} source={source} now={now} /> ))} {groups.map((group) => ( <div key={group.environmentId} className="flex flex-col gap-6"> {group.environmentLabel ? ( <h2 className="text-xs tracking-wide text-muted-foreground uppercase"> {group.environmentLabel} </h2> ) : null} {group.providers.map((provider) => ( <ProviderLimits key={provider.instanceId} provider={provider} environmentId={group.environmentId} now={now} /> ))} </div> ))} </div> );}
import {
type EnvironmentId,
type ProviderConsumeResetCreditOutcome,
ProviderInstanceId,
ServerProvider,
ServerProviderResetCredits,
ServerProviderUsageWindow,
UsageLimitSourceAccount,
UsageLimitSourceSnapshot,
UsageProviderKind,
} from "@t3tools/contracts";
import { useAtomValue } from "@effect/atom-react";
import {
collectLimitSources,
collectLimitsGroups,
elapsedShare,
formatDuration,
formatResetsIn,
limitsNotice,
type LimitPace,
paceOf,
providerLimitsLabel,
} from "@t3tools/shared/usageLimits";
import { GaugeIcon, TrendingDownIcon, TrendingUpIcon } from "lucide-react";
import { Fragment, useState } from "react";
import { usePrimarySettings } from "../../hooks/useSettings";
import { environmentPresentations } from "../../state/presentation";
import { serverEnvironment } from "../../state/server";
import { useAtomCommand } from "../../state/use-atom-command";
import { formatUpcomingTimestamp } from "../../timestampFormat";
import { ProviderInstanceIcon } from "../chat/ProviderInstanceIcon";
import { getDriverOption } from "../settings/providerDriverMeta";
import { RedactedSensitiveText } from "../settings/RedactedSensitiveText";
import {
AlertDialog,
AlertDialogClose,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogPopup,
AlertDialogTitle,
} from "../ui/alert-dialog";
import { Button } from "../ui/button";
import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";
import { PROVIDER_PRESENTATION } from "./usageProviders";
const PACE: Record<LimitPace, { readonly label: string; readonly icon: typeof GaugeIcon }> = {
ahead: { label: "Ahead of pace: spending faster than the window elapses", icon: TrendingUpIcon },
on: { label: "On pace with the window", icon: GaugeIcon },
under: { label: "Under pace: headroom left for the rest of the window", icon: TrendingDownIcon },
};
/** The series colour the cost chart uses for this driver, so the two views read as one. */
function barColor(driver: ServerProvider["driver"]): string {
const kind: UsageProviderKind | undefined =
driver === "codex" ? "codex" : driver === "claudeAgent" ? "claude" : undefined;
return kind ? PROVIDER_PRESENTATION[kind].color : "var(--foreground)";
}
/** Pace as a glyph with the words on hover. */
function PaceIcon({ pace }: { readonly pace: LimitPace }) {
const Icon = PACE[pace].icon;
return (
<Tooltip>
<TooltipTrigger
render={
<span
role="img"
aria-label={PACE[pace].label}
className="inline-flex text-muted-foreground"
/>
}
>
<Icon className="size-3.5" aria-hidden />
</TooltipTrigger>
<TooltipPopup side="top">{PACE[pace].label}</TooltipPopup>
</Tooltip>
);
}
/**
* One window as a full-width bar from the moment it opened to its reset.
* The fill is the share of quota spent; the hairline is how far into the
* window the clock is, which is also where even spending would have put the
* fill. Hover for the exact figures and reset time.
*/
function WindowBar({
color,
window,
now,
}: {
readonly color: string;
readonly window: ServerProviderUsageWindow;
readonly now: number;
}) {
const timestampFormat = usePrimarySettings((settings) => settings.timestampFormat);
const used = Math.max(0, Math.min(100, window.usedPercent));
const elapsed = elapsedShare(window, now);
const resetsIn = formatResetsIn(window, now);
const resetsAt = window.resetsAt
? formatUpcomingTimestamp(window.resetsAt, timestampFormat, now)
: null;
const summary = `${window.label}: ${Math.round(used)}% used${
elapsed === null ? "" : `, ${Math.round(elapsed * 100)}% of the window elapsed`
}${resetsIn ? `, ${resetsIn}` : ""}`;
return (
<Tooltip>
<TooltipTrigger
render={
<div
role="img"
aria-label={summary}
tabIndex={0}
className="relative h-6 cursor-default rounded-full outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
/>
}
>
<div className="absolute inset-x-0 inset-y-1.5 rounded-full bg-muted" />
{used > 0 ? (
<div
className="absolute inset-y-1.5 left-0 rounded-full"
style={{ width: `${used}%`, backgroundColor: color }}
/>
) : null}
{elapsed !== null ? (
<span
aria-hidden
className="absolute inset-y-0.5 w-px -translate-x-1/2 bg-foreground/60"
style={{ left: `${elapsed * 100}%` }}
/>
) : null}
</TooltipTrigger>
<TooltipPopup side="top" className="max-w-72 text-xs">
<div className="flex flex-col gap-0.5">
<span className="text-foreground">
{Math.round(used)}% used
{elapsed !== null ? ` · ${Math.round(elapsed * 100)}% of the window elapsed` : ""}
</span>
{elapsed !== null ? (
<span className="text-muted-foreground">The line is where even spending would be.</span>
) : null}
{resetsAt ? (
<span className="text-muted-foreground">
Resets {resetsAt}
{resetsIn ? ` · ${resetsIn}` : ""}
</span>
) : null}
</div>
</TooltipPopup>
</Tooltip>
);
}
/** One account's windows as rows: label and percent, bar, pace and countdown. */
function LimitWindows({
driver,
windows,
now,
}: {
readonly driver: ServerProvider["driver"];
readonly windows: ReadonlyArray<ServerProviderUsageWindow>;
readonly now: number;
}) {
const color = barColor(driver);
return (
<div className="grid grid-cols-[11rem_minmax(0,1fr)_7rem] gap-x-4 gap-y-1">
{windows.map((window, index) => {
// Windows that reset together show the countdown once.
const previous = windows[index - 1];
const sharesReset =
previous?.resetsAt !== undefined && previous.resetsAt === window.resetsAt;
const pace = paceOf(window, now);
const resetsIn = formatResetsIn(window, now);
return (
<Fragment key={window.id}>
<span className="flex min-w-0 items-center gap-2 text-xs">
<span className="truncate text-muted-foreground">{window.label}</span>
<span className="ms-auto shrink-0 font-medium text-foreground tabular-nums">
{Math.round(window.usedPercent)}%
</span>
</span>
<WindowBar color={color} window={window} now={now} />
<span className="flex items-center gap-2 text-xs text-muted-foreground tabular-nums">
{pace ? <PaceIcon pace={pace} /> : null}
<span className="ms-auto shrink-0">{sharesReset ? "" : (resetsIn ?? "")}</span>
</span>
</Fragment>
);
})}
</div>
);
}
/**
* Heading shared by local providers and source accounts: icon, driver, instance, plan,
* and the signed-in email blurred until clicked, as provider settings do.
*/
function AccountHeading({
driver,
label,
instanceLabel,
plan,
email,
accentColor,
}: {
readonly driver: ServerProvider["driver"];
readonly label: string;
readonly instanceLabel: string;
readonly plan: string | undefined;
readonly email: string | undefined;
readonly accentColor?: string | undefined;
}) {
return (
<h2 className="flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 text-sm font-medium text-foreground">
<ProviderInstanceIcon
driverKind={driver}
displayName={instanceLabel}
accentColor={accentColor}
showBadge={Boolean(accentColor)}
indicatorBackground="var(--background)"
className="size-5"
iconClassName="size-4 text-foreground/80"
/>
<span className="truncate">{label}</span>
{instanceLabel !== label ? (
<span className="min-w-0 truncate text-xs font-normal text-muted-foreground">
· {instanceLabel}
</span>
) : null}
{plan ? <span className="font-normal text-muted-foreground">· {plan}</span> : null}
{email ? (
<RedactedSensitiveText
value={email}
ariaLabel="Toggle account email visibility"
revealTooltip="Click to reveal email"
hideTooltip="Click to hide email"
/>
) : null}
</h2>
);
}
function ProviderLimits({
provider,
environmentId,
now,
}: {
readonly provider: ServerProvider;
readonly environmentId: EnvironmentId;
readonly now: number;
}) {
const limits = provider.usageLimits;
if (!limits) return null;
const notice = limitsNotice(limits);
return (
<section className="flex flex-col gap-3">
<AccountHeading
driver={provider.driver}
label={getDriverOption(provider.driver)?.label ?? String(provider.driver)}
instanceLabel={providerLimitsLabel(provider, (driver) => getDriverOption(driver)?.label)}
plan={provider.auth.label}
email={provider.auth.email}
accentColor={provider.accentColor}
/>
{notice ? (
<span className="text-xs text-muted-foreground">{notice}</span>
) : (
<LimitWindows driver={provider.driver} windows={limits.windows} now={now} />
)}
{limits.resetCredits ? (
<ResetCredits
environmentId={environmentId}
instanceId={provider.instanceId}
credits={limits.resetCredits}
now={now}
/>
) : null}
</section>
);
}
const OUTCOME_TEXT: Record<ProviderConsumeResetCreditOutcome, string> = {
reset: "Reset applied. Your windows have cleared.",
nothingToReset: "Nothing to reset right now.",
noCredit: "No reset credit left.",
alreadyRedeemed: "That credit was already redeemed.",
};
/**
* Banked reset credits with a confirmed redeem action. Redeeming spends a
* credit the provider granted the user, so it never fires on a bare click.
*/
function ResetCredits({
environmentId,
instanceId,
credits,
now,
}: {
readonly environmentId: EnvironmentId;
readonly instanceId: ProviderInstanceId;
readonly credits: ServerProviderResetCredits;
readonly now: number;
}) {
const consume = useAtomCommand(serverEnvironment.consumeResetCredit, { reportFailure: false });
const [confirming, setConfirming] = useState(false);
const [busy, setBusy] = useState(false);
const [status, setStatus] = useState<string | null>(null);
if (credits.availableCount === 0 && status === null) return null;
const expiresIn = credits.nextExpiresAt
? formatDuration(Date.parse(credits.nextExpiresAt) - now)
: null;
const summary =
credits.availableCount === 0
? "No reset credits banked"
: `${credits.availableCount} ${credits.availableCount === 1 ? "reset credit" : "reset credits"} banked${
expiresIn ? ` · next expires in ${expiresIn}` : ""
}`;
const redeem = async () => {
setConfirming(false);
setBusy(true);
setStatus(null);
const result = await consume({ environmentId, input: { instanceId } });
setBusy(false);
if (result._tag === "Success") {
setStatus(OUTCOME_TEXT[result.value.outcome]);
return;
}
setStatus(
"error" in result.cause && result.cause.error instanceof Error
? result.cause.error.message
: "Could not use the reset credit.",
);
};
return (
<div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground">
<span className="tabular-nums">{summary}</span>
{credits.availableCount > 0 ? (
<Button size="xs" variant="outline" disabled={busy} onClick={() => setConfirming(true)}>
{busy ? "Using credit…" : "Use a reset credit"}
</Button>
) : null}
{status ? <span className="text-foreground">{status}</span> : null}
<AlertDialog open={confirming} onOpenChange={setConfirming}>
<AlertDialogPopup>
<AlertDialogHeader>
<AlertDialogTitle>Use a reset credit?</AlertDialogTitle>
<AlertDialogDescription>
This redeems one credit on your account and clears the current rate-limit windows. It
cannot be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogClose render={<Button variant="outline" />}>Cancel</AlertDialogClose>
<Button onClick={() => void redeem()}>Use credit</Button>
</AlertDialogFooter>
</AlertDialogPopup>
</AlertDialog>
</div>
);
}
/** One account pooled by a usage-limit source, drawn like a provider row. */
function SourceAccountLimits({
account,
sourceKind,
now,
}: {
readonly account: UsageLimitSourceAccount;
readonly sourceKind: string;
readonly now: number;
}) {
const notice = limitsNotice(account.usageLimits);
return (
<section className="flex flex-col gap-3">
<AccountHeading
driver={account.driver}
label={getDriverOption(account.driver)?.label ?? String(account.driver)}
instanceLabel={sourceKind}
plan={account.plan}
email={account.email}
/>
{notice ? (
<span className="text-xs text-muted-foreground">{notice}</span>
) : (
<LimitWindows driver={account.driver} windows={account.usageLimits.windows} now={now} />
)}
</section>
);
}
const SOURCE_KIND_LABEL: Record<UsageLimitSourceSnapshot["kind"], string> = {
cliproxy: "CLI Proxy",
};
type LimitsSource = ReturnType<typeof collectLimitSources>[number];
/** Read-only accounts pooled by a configured usage source. */
function SourceLimits({ source, now }: { readonly source: LimitsSource; readonly now: number }) {
const kind = SOURCE_KIND_LABEL[source.kind];
return (
<div className="flex flex-col gap-6">
{source.error ? (
<span className="text-xs text-muted-foreground">{source.error}</span>
) : source.accounts.length === 0 ? (
<span className="text-xs text-muted-foreground">
{source.hiddenAccountCount > 0
? "All accounts are shown by connected providers."
: "No accounts reported."}
</span>
) : (
source.accounts.map((account) => (
<SourceAccountLimits key={account.id} account={account} sourceKind={kind} now={now} />
))
)}
</div>
);
}
/**
* Subscription quota windows from every connected environment's providers.
* Countdowns anchor to render time rather than ticking: a live clock would
* repaint the page every minute for no decision-changing gain.
*/
export function UsageLimitsSection() {
const presentations = useAtomValue(environmentPresentations.presentationsAtom);
const groups = collectLimitsGroups(presentations);
const sources = collectLimitSources(presentations);
// Anchored once per mount on purpose: countdowns must not tick (see below).
const [now] = useState(() => Date.now());
return (
<div className="flex flex-col gap-8">
{groups.length === 0 && sources.length === 0 ? (
<p className="text-sm text-muted-foreground">
No provider on a connected environment reports subscription limits.
</p>
) : null}
{sources.map((source) => (
<SourceLimits key={source.key} source={source} now={now} />
))}
{groups.map((group) => (
<div key={group.environmentId} className="flex flex-col gap-6">
{group.environmentLabel ? (
<h2 className="text-xs tracking-wide text-muted-foreground uppercase">
{group.environmentLabel}
</h2>
) : null}
{group.providers.map((provider) => (
<ProviderLimits
key={provider.instanceId}
provider={provider}
environmentId={group.environmentId}
now={now}
/>
))}
</div>
))}
</div>
);
}