Skip to content

Plan limits ​

What is left of each plan: the session and weekly windows of every CLI and account, as the host last read them.

tsx
import { UsageLimits } from '@adecore/agents-react/usage/UsageLimits';
import { UsageLimitsCard } from '@adecore/agents-react/usage/UsageLimitsCard';
tsx
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.

tsx
<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.

Licenses and third-party notices are listed in each package.