import type { Actor } from '../types.js';
/** The span a quota window counts over, in UTC. */
export type QuotaPeriod = 'day' | 'month';
/** One budget window: what was spent in it, and the ceiling when there is one. */
export interface QuotaWindow {
    period: QuotaPeriod;
    /**
     * Tokens used in the window. Absent → the budget does not count tokens (a USD-only spend cap, such
     * as an AI gateway's) — never a fabricated `0`.
     */
    usedTokens?: number;
    /** Absent → no token ceiling on this window. */
    limitTokens?: number;
    usedUsd: number;
    /** Absent → no spend ceiling on this window. */
    limitUsd?: number;
    /** ISO-8601 instant the window starts over (next UTC midnight, first of next month). */
    resetsAt?: string;
    /**
     * The soft limit: the share of a ceiling (`0..1`, e.g. `0.8`) past which a client should warn
     * that the budget is running out. Absent → no warning for this window.
     */
    warnAt?: number;
}
/** Which window stopped the actor, when one did. */
export interface QuotaBlock {
    period: QuotaPeriod;
    /** Words a client can show ("Monthly AI budget reached"). */
    reason?: string;
}
/** A window past its soft limit ({@link QuotaWindow.warnAt}) but not exhausted. */
export interface QuotaWarning {
    period: QuotaPeriod;
    /** How much of the window's ceiling is used, `0..1` (the larger of spend and tokens). */
    ratio: number;
    /** Words a client can show ("80% of your monthly AI budget used"). */
    reason?: string;
}
/** What `GET <base>/quota` answers. */
export interface QuotaReport {
    windows: QuotaWindow[];
    /** Present when a window is exhausted — a send will be refused until it resets. */
    blocked?: QuotaBlock;
    /**
     * Present when a window crossed its `warnAt` and none is exhausted — the fullest one. A client
     * may also derive it from the windows ({@link quotaWarning}); the server's wins.
     */
    warning?: QuotaWarning;
}
export interface QuotaQuery {
    actor: Actor;
    /** The instant to report for; defaults to now. */
    now?: Date;
}
/**
 * The actor's budget across windows — the read behind `GET <path>/quota` and, when `quota` in
 * `config/agent.ts` resolves to one (`quotas.windows({ … })`, or your own), the gate a send passes: a
 * report with `blocked` refuses the turn with `429` before it starts.
 *
 * Without one the provider reports from the usage ledger (`LedgerQuotaProvider`), informational
 * only. A host with its own budget (an AI-gateway spend cap, a plan's monthly allowance) implements
 * this. The shape is `@dudousxd/nestjs-agent-core`'s, copied.
 */
export interface QuotaProvider {
    report(query: QuotaQuery): Promise<QuotaReport>;
}
/** The first window whose token or spend ceiling is reached, as a {@link QuotaBlock}. */
export declare function exhaustedWindow(windows: readonly QuotaWindow[]): QuotaBlock | undefined;
/** How much of `window`'s ceilings is used, `0..1+` (the larger of spend and tokens), or `null`. */
export declare function quotaUsedRatio(window: QuotaWindow): number | null;
/**
 * The fullest window past its `warnAt`, as a {@link QuotaWarning} — `undefined` when none is, or
 * when one is exhausted (that is `blocked`, not a warning).
 */
export declare function quotaWarning(windows: readonly QuotaWindow[]): QuotaWarning | undefined;
/** The UTC day range (`YYYY-MM-DD`, inclusive) and reset instant of `period` around `now`. */
export declare function quotaPeriodRange(period: QuotaPeriod, now: Date): {
    fromDay: string;
    toDay: string;
    resetsAt: string;
};
/** Is this a {@link QuotaProvider} (rather than a daily `QuotaStore`)? */
export declare function isQuotaProvider(value: unknown): value is QuotaProvider;
/** A send refused because a budget window is exhausted — the chat route's `429 quota_exceeded`. */
export declare class QuotaBlockedError extends Error {
    readonly period: QuotaPeriod;
    constructor(period: QuotaPeriod, message: string);
}
//# sourceMappingURL=quota-provider.d.ts.map