/**
 * The ONE admission an image's bytes pass before they reach the model as an `ImageContent` block —
 * whether a file supplied them (the Read tool's image lane), a caller did (`TaskSpec.images`' inline
 * arm, a user attachment) or a tool returned them (the tool-result seat below). Four steps, in this order:
 *
 *   ① the claimed type is one the content API accepts (png / jpeg / gif / webp — the four
 *      {@link imageMagicMatches} can verify);
 *   ② the raw bytes are within the read cap (5 MiB without a downsampler, 64 MiB with one);
 *   ③ the bytes carry the claimed type's signature — an empty / text / mis-named "png" would
 *      otherwise become a malformed block that 400s the NEXT whole provider request;
 *   ④ optional downsample (when a downsampler is supplied; a processing failure keeps the original
 *      bytes, CC's catch → createImageResponse(original)), then the provider's hard limit, which is on the
 *      BASE64 length, not raw bytes.
 *
 * The answer is structured; each carrier words its own refusal (the Read tool speaks to the model, the
 * task door to the caller). The block it admits is built from the bytes it checked — never from a
 * caller's string it did not decode. A document's bytes pass the same shape of admission
 * ({@link admitDocumentBytes}: `application/pdf`, the whole-send cap, the `%PDF-` signature).
 *
 * THE TOOL-RESULT SEAT ({@link admitToolResultMedia}): every executed call's result passes the loop's one
 * post-execution half (`finalizeToolOutcome`) — an engine tool's, an MCP tool's converted content, a host
 * tool's own return, a resumed approved call's, and whatever a `tool_result` hook put in their place — so
 * the media blocks of every supply are admitted there, once, after the last hand that can change them and
 * before the frame and the transcript read them. A block whose bytes the admission refuses becomes a text
 * block that names the tool, the refusal and the size — never the bytes, and never silently nothing.
 */
import type { DocumentContent, ImageContent } from "../internal/llm.js";
import { type ImageDimensions, type ImageDownsampler } from "./image-downsample.js";
import { type MediaBlock } from "./media-byte-cap.js";
/** Byte cap on a Read-image WITHOUT a downsampler: an image file is returned AS a visual
 *  `ImageContent` block (base64) rather than refused. Bounded so a huge image cannot blow the request.
 *  This stat-time cap only bounds the READ; the accept/refuse decision is the base64 gate below (the
 *  provider limit is on base64 LENGTH, so the effective no-sharp accept bound is raw ≤ 3.75MB). */
export declare const MAX_IMAGE_READ_BYTES: number;
/** Byte cap on a Read-image WITH a downsampler: sharp can shrink a big photo to CC's 2000×2000/3.75MB
 *  target, so the smaller hard refusal does not apply (CC readImageWithTokenBudget reads the file
 *  unbounded; we keep an OOM sanity bound — deliberate delta, camera photos fit comfortably). */
export declare const MAX_IMAGE_DOWNSAMPLE_INPUT_BYTES: number;
/** Max raw size sent whole as a document block (CC `PDF_TARGET_RAW_SIZE`). */
export declare const PDF_TARGET_RAW_SIZE: number;
/** Verify the raw bytes actually ARE the image format the extension claims (magic-number sniff). Extension alone
 *  is forgeable: a `.png` holding text / an empty file / a truncated blob would otherwise become a malformed
 *  `ImageContent` that makes the NEXT provider request fail (400). Pure — no I/O. */
export declare function imageMagicMatches(bytes: Uint8Array, mimeType: string): boolean;
/** True when the bytes start with the `%PDF-` magic. Magic outranks extension both ways: a mis-named
 *  `.pdf` without it is refused, and a non-`.pdf` file carrying it is read AS a PDF. */
export declare function pdfMagicMatches(bytes: Uint8Array): boolean;
/** The image types the content API accepts — the only ones a signature check can verify. */
export declare const ADMITTED_IMAGE_MIME_TYPES: readonly ["image/png", "image/jpeg", "image/gif", "image/webp"];
/** The raw-byte read cap for an image, with or without a downsampler. */
export declare function imageReadCap(downsampler: ImageDownsampler | undefined): number;
export type ImageAdmission = {
    ok: true;
    block: ImageContent;
    /** The raw byte count of the bytes checked (before any downsample). */
    originalSize: number;
    /** Measured by the downsampler; absent without one (never fabricated). */
    dimensions?: ImageDimensions;
    /** True when the downsampler actually changed the pixel size. */
    resized: boolean;
} | {
    ok: false;
    reason: "mime_unsupported" | "magic_mismatch";
    rawBytes: number;
} | {
    ok: false;
    reason: "raw_too_large";
    rawBytes: number;
    cap: number;
}
/** `base64` is the encoding that failed the limit (the caller words the refusal from its length). */
 | {
    ok: false;
    reason: "base64_too_large";
    rawBytes: number;
    base64: string;
};
export declare function admitImageBytes(bytes: Uint8Array, claimedMime: string, downsampler: ImageDownsampler | undefined): Promise<ImageAdmission>;
/** The document types the content API accepts — the one a signature check can verify. */
export declare const ADMITTED_DOCUMENT_MIME_TYPES: readonly ["application/pdf"];
export type DocumentAdmission = {
    ok: true;
    block: DocumentContent;
    originalSize: number;
} | {
    ok: false;
    reason: "mime_unsupported" | "magic_mismatch";
    rawBytes: number;
} | {
    ok: false;
    reason: "raw_too_large";
    rawBytes: number;
    cap: number;
};
/** A document's bytes: the claimed type is `application/pdf`, the raw bytes are within the whole-send cap
 *  ({@link PDF_TARGET_RAW_SIZE}, the Read tool's), and they start with `%PDF-`. */
export declare function admitDocumentBytes(bytes: Uint8Array, claimedMime: string): DocumentAdmission;
/** Why the tool-result seat refused a media block: the admissions' own words (an image's four — a document's are among
 *  them), or `undecodable` — the block carried no base64 string to decode. */
export type MediaRefusalReason = "undecodable" | "mime_unsupported" | "raw_too_large" | "magic_mismatch" | "base64_too_large";
/** One media block the seat refused: its type, the refusal, its decoded size, the bound it exceeded (the raw-byte cap for
 *  `raw_too_large`, the base64 length limit for `base64_too_large`), and its media type when it can be one. */
export interface ToolResultMediaRefusal {
    type: MediaBlock["type"];
    reason: MediaRefusalReason;
    bytes: number;
    limit?: number;
    mimeType?: string;
}
/** What the seat made of one result's content: every media block rebuilt from its checked bytes or replaced, in its slot,
 *  by its placeholder; and the refusals. */
export interface ToolResultMediaAdmission {
    content: unknown[];
    refused: ToolResultMediaRefusal[];
}
/**
 * The tool-result seat's admission over one executed call's content: `undefined` when no block claims a media type (the
 * content stands as it is, and nothing is awaited); otherwise every block is read once into a new array, each media
 * block admitted — rebuilt from the bytes it checked, or replaced in its slot by a placeholder naming `toolName` and the
 * refusal. Total: a content whose blocks cannot be read is not media this seat can admit or refuse, and is left as it is.
 */
export declare function admitToolResultMedia(content: unknown, toolName: string): Promise<ToolResultMediaAdmission> | undefined;
