Plan limits
What is left of each plan: the session and weekly windows of every CLI and account, as the host last read them.
import { UsageLimits } from '@adecore/agents-react/usage/UsageLimits';
import { UsageLimitsCard } from '@adecore/agents-react/usage/UsageLimitsCard';import { useNow } from '@adecore/ui';
import { AccountLimitsList, LimitsList, WindowBar } from '@adecore/agents-react/usage/LimitsList';
import { useLimitGroups } from '@adecore/agents-react/usage/limits';
import { UsageLimits } from '@adecore/agents-react/usage/UsageLimits';
import { usageLimits } from '../shared/agents-data.ts';
import { AgentDemo } from '../shared/agents.tsx';
const limits = usageLimits();
function Lists() {
const now = useNow(60_000);
const groups = useLimitGroups(limits);
return (
<div className="flex w-full flex-col gap-8">
<UsageLimits />
<div className="grid gap-6 md:grid-cols-2">
<div className="flex flex-col gap-2">
<span className="text-xs text-text-muted">LimitsList</span>
<LimitsList limits={limits} now={now} compact />
</div>
<div className="flex flex-col gap-2">
<span className="text-xs text-text-muted">AccountLimitsList</span>
<AccountLimitsList groups={groups} now={now} />
</div>
</div>
<div className="flex max-w-sm flex-col gap-2">
<span className="text-xs text-text-muted">WindowBar</span>
<WindowBar window={limits.providers[2]!.windows[0]!} now={now} compact={false} />
</div>
</div>
);
}
export default function UsageLimitsDemo() {
return (
<AgentDemo>
<Lists />
</AgentDemo>
);
}UsageLimits() is the section of the usage page: a card per account with a bar per window, when it resets, and why an account has no numbers, with a way to sign in when the host has openLogin. It reads the scope in context.
UsageLimitsCard({ children }) puts the same numbers in a hover card over a trigger of your own, such as a button in a sidebar. It asks the host only once the card opens.
<UsageLimitsCard>
<Button variant="secondary">Plan limits</Button>
</UsageLimitsCard>Reading the limits
useUsageLimits() answers the scope's UsageLimitsSnapshot, or null until the host answered. Every view that shows the limits of a host shares one read: the first asks usage.limits and follows usage.limitsChanged, the last to unmount stops following. It never makes a transport connect.
useLimitGroups(limits) groups the windows per CLI with the scope's accounts, so an account that is on but signed out still has a row that says why; limitGroups(snapshot, accounts) does it outside React. A window with no reading is unknown, not room left.
Lists
LimitsList({ limits, now, compact? }) lists every CLI with its windows; compact is for a list inside a hover card. AccountLimitsList({ groups, now }) does the same per account, once a CLI has several. WindowBar({ window, now, compact }) is one bar with how much is used and when it resets.
limitsOfAccount, sessionWindow, continueTarget and hasUnreadAccount in agents/account-limits, and nextReset, explain and accountNote in usage/limit-groups, are the logic behind them.