/**
 * receiptDigests — what a run's receipts have already hashed, so each piece of
 * a request is hashed ONCE per run instead of once per call.
 *
 * Role:  Memo. A plain data structure the receipt mint (`receipt.ts` ·
 *        `buildReceipt`) reads and fills; it hashes nothing itself, reads no
 *        scope and emits nothing.
 * Reads: what the mint hands it.
 * Emits: N/A.
 *
 * ── WHY IT EXISTS ───────────────────────────────────────────────────────────
 * An agent's request at call k is the request at call k−1 plus what the loop
 * appended — and the mint used to hash every message of it again, on every
 * call. Measured on an agent run with 1,000-row tool results: SHA-256 input
 * grew with the square of the iteration count, and the mint was the largest
 * single cost of the run (63% of its CPU at 40 iterations, under a caching
 * provider). The digests themselves never needed to change: a receipt's hashes
 * are functions of the bytes, so a message hashed at call 3 has the same hash
 * at call 30. This keeps them.
 *
 * ── THE TWO LOOKUPS ─────────────────────────────────────────────────────────
 *   BY PREIMAGE  `hash(preimage)` — the salted hashes of the per-call pieces
 *                that are not messages (system text, system pieces, tool
 *                schemas), keyed by the exact string that was hashed. Exact by
 *                construction: a hash is a function of its preimage, so a hit
 *                returns what recomputing would return.
 *   BY OBJECT    `message(m)` — what was derived from one message OBJECT: its
 *                entry hash, its transform-chain digest, whether it serializes,
 *                and its request measurement (`requestMeasurement.ts`), so a
 *                message the run has already seen costs no string building at
 *                all. It keeps DIGESTS and counts, never a copy of the message's
 *                text — a 1,000-row tool result is not held twice. Valid only while
 *                the object's own fields are the values they were: every field
 *                is compared by identity on each hit, and a mismatch derives
 *                again. Committed state is never edited in place (footprintjs's
 *                immutable-after-swap law), so a hit is the common case — the
 *                agent's history hands the mint the same message objects call
 *                after call.
 *
 * ── WHAT IT DOES NOT CHANGE ─────────────────────────────────────────────────
 * Every hash a receipt carries is the hash it carried before this memo existed:
 * same preimage, same salt, same digest. A receipt minted with the memo and one
 * minted without it are byte-identical, and so is the request measurement —
 * pinned by test/core/agent/receipt/receipt-incremental.test.ts.
 *
 * The one assumption a hit makes: a message's NESTED values (`toolCalls`,
 * `args`, `thinkingBlocks`) are not edited in place while the message object
 * is reused. The agent's history is committed state, which is never edited in
 * place; a caller that hands the mint its own objects and then mutates one
 * deep inside must hand a new object instead.
 *
 * ── LIFETIME ────────────────────────────────────────────────────────────────
 * One memo per run, bound to the run id (the salt). `forRun` hands back the
 * current run's memo, and a different run id starts a fresh one — so a reused
 * agent never carries one run's strings into the next.
 *
 * Within a run, the two string memos (BY PREIMAGE, and the transform chain's
 * links) keep TWO CALLS' worth — the call being minted and the one before it.
 * Each `forRun` is one mint, and it rotates them. A piece that repeats from one
 * call to the next (a system prompt, a tool schema, the chain's prefix) is
 * found; a piece that changes every call (a system prompt with the time in it)
 * is not kept past the next call. What the memo holds is bounded by two
 * requests' worth — their non-message pieces and one chain link per message —
 * never by how many calls the run made. The BY OBJECT memo is weak — it lives
 * as long as the message objects do.
 *
 * ── TOTAL ───────────────────────────────────────────────────────────────────
 * A receipt is bookkeeping and must never stop a run. A message whose fields
 * cannot be read (a throwing getter on an object a caller handed in) is not
 * memoized: `message()` hands back a fresh, unkept record and the mint derives
 * everything from the message as it would with no memo at all.
 */
import type { MessageMeasure, MessageMeasureCache } from './requestMeasurement.js';
/** What one message object has already been turned into. */
export interface MessageDigests {
    /** `messageDigestInput(m)` hashed — the receipt's `messages.entries[].hash`. */
    entryHash?: string;
    /**
     * Whether `stableJson([m])` — the message as one array element — produced a
     * value. Read by the cache comparison, which is `'unknown'` when a message
     * cannot be serialized.
     */
    serializable?: boolean;
    /** `H(stableJson([m]) ?? UNSERIALIZABLE)` — the transform chain's digest of
     *  this message (`receipt.ts` · `transformHashOf`). Kept as the digest, never
     *  as the JSON, so the memo holds no copy of a message's text. */
    elementDigest?: string;
    /** The message as `measureRequest` measured it at a request's
     *  `messages[i]` (`requestMeasurement.ts` · `MessageMeasure`). */
    measure?: MessageMeasure;
}
/** One run's memo. */
export interface RunDigests extends MessageMeasureCache {
    /** The run id every hash in this memo is salted with. */
    readonly runId: string;
    /** The salted hash of `preimage`, computed by `compute` the first time only. */
    hash(preimage: string, compute: () => string): string;
    /** What has been derived from `message` while its fields are unchanged. */
    message(message: object): MessageDigests;
    /** The chain link after `previous` and `digest` — see `receipt.ts` ·
     *  `transformHashOf`. Computed by `compute` the first time only. */
    link(previous: string, digest: string, compute: () => string): string;
    /** @internal Strings the two string memos hold right now — pinned by
     *  test/core/agent/receipt/receipt-incremental.test.ts (bounded by two calls). */
    retained(): number;
}
/**
 * A memo the receipt mint keeps across the calls of a run. Create one per
 * agent; it rebinds itself when the run id changes.
 *
 * @example
 * ```ts
 * const digests = createReceiptDigests();
 * buildReceipt(callOne, digests);   // hashes every piece
 * buildReceipt(callTwo, digests);   // hashes only what call two added
 * ```
 */
export interface ReceiptDigests {
    /** The memo for `runId` — the current one, or a fresh one for a new run. */
    forRun(runId: string): RunDigests;
}
/** Start an empty memo. See {@link ReceiptDigests}. */
export declare function createReceiptDigests(): ReceiptDigests;
