/** Counts only: the initial prepared request at the library's provider port.
 * No token estimate, payload retention, retry total or vendor wire claim. */
export interface RequestJsonSize {
    /** UTF-16 code units in the JSON representation, including JSON punctuation. */
    readonly jsonChars: number;
    /** UTF-8 bytes in that same JSON representation. */
    readonly jsonBytes: number;
}
type MeasurementBoundary = {
    readonly boundary: 'initial-prepared-request';
    readonly format: 'json-utf8-v1';
};
/** Sizes describe JSON of the canonical request, excluding its root `signal`.
 * Slot values are serialized separately and do not sum to the request total.
 * Missing slots were absent/undefined; an empty array still has JSON size. */
export type RequestMeasurement = MeasurementBoundary & ({
    readonly status: 'measured';
    readonly total: RequestJsonSize;
    readonly slots: {
        readonly systemPrompt?: RequestJsonSize;
        readonly messages?: RequestJsonSize;
        readonly tools?: RequestJsonSize;
    };
} | {
    readonly status: 'unavailable';
    readonly reason: 'unsupported-value' | 'cyclic-value' | 'measurement-limit';
});
/**
 * One message object as {@link measureRequest} measured it at a request's
 * `messages[i]` — the counts its walk added and its JSON size, so a later call
 * that hands the same message adds the counts instead of walking it again.
 * Kept only for a walk that raised nothing (a value the walk refuses is walked
 * again, and refused again, every call).
 */
export interface MessageMeasure {
    /** Values the walk visited inside this message, the message included. */
    readonly visited: number;
    /** Characters the walk counted inside it (string values and keys). */
    readonly chars: number;
    /** The highest value-budget demand its walk made, relative to the count it
     *  started from — `visited` plus the largest array/object it sized up front. */
    readonly need: number;
    /** Its JSON, as one array element: UTF-16 code units and UTF-8 bytes. */
    readonly json: RequestJsonSize;
}
/** Where {@link measureRequest} keeps a message's measurement across the calls
 *  of one run — the receipt memo (`receiptDigests.ts`) is the one owner. */
export interface MessageMeasureCache {
    measureOf(message: object): MessageMeasure | undefined;
    keep(message: object, measure: MessageMeasure): void;
}
/** Internal receipt helper. Read plain data through descriptors so telemetry
 * does not invoke getters or custom toJSON. Unsupported values fail open with
 * a reason code, never exception text. Transport adapters remain authoritative
 * for what they actually serialize; this helper does not validate requests.
 *
 * INCREMENTAL. The request's `messages` are measured one element at a time and
 * the sizes composed (`[` + elements joined by `,` + `]`, spliced into the rest
 * of the request) — JSON is compositional, so the sum IS the size of the whole.
 * With a `cache`, a message object already measured this run adds its kept
 * counts and size instead of being walked again: an agent's request at call k
 * is call k−1's plus what the loop appended, and measuring it whole every call
 * grew with the square of the iteration count. Every limit is checked against
 * the same running counts as a whole walk, so the result — `measured` or the
 * reason it is `unavailable` — is the one the whole walk gives; pinned by
 * test/core/agent/receipt/receipt-incremental.test.ts. A cache hit assumes what
 * the receipt memo assumes: the message's nested values were not edited in
 * place (`receiptDigests.ts`). */
export declare function measureRequest(request: unknown, cache?: MessageMeasureCache): RequestMeasurement;
export {};
