/**
 * request — an AG-UI request (`RunAgentInput`) read as UNTRUSTED browser input,
 * and the one turn it may ask for.
 *
 * Three steps. The first is the app's to replace; the other two are the CORE,
 * and run whichever reader produced the request — so a reader can map another
 * body onto a turn, and never weaken a rule:
 *
 *   the READER         a body → an {@link AgUiTurnRequest}. The default takes
 *                      the body as an AG-UI `RunAgentInput`; a gateway that
 *                      sends its own body shape passes its own
 *                      ({@link AgUiRequestReader}). Mapping only — it decides
 *                      nothing below;
 *   readAgUiRequest    what a custom reader produced, copied as plain JSON (so
 *                      a getter or a proxy cannot answer the check one way and
 *                      the plan another; the default reader's body is parsed
 *                      JSON already and is read as it is), then
 *   readAgUiRunInput   its SHAPE, field by field, and
 *                      the ids' FORMAT and length — nothing here is trusted,
 *                      nothing the server holds is read;
 *   planAgUiTurn       the turn, from the request AND what the server holds
 *                      for the bound conversation.
 *
 * The core's steps refuse by NAME (a `WireRequestRefusal`: its own status and
 * code; the field named, the value never quoted back).
 *
 * WHAT A REQUEST MAY DECIDE, and what it may not:
 *   - the newest USER message is the run's message. Nothing else the browser
 *     sends is ever conversation: its assistant and tool messages are its own
 *     copy of what the server said, and the server's copy is the one kept
 *     (`sessions`, or the agent's memory under the bound session). A system or
 *     developer message is refused — the agent's instructions are its own;
 *   - an ANSWER is taken only for the pause the server is keeping, matched to
 *     the ids that pause handed out (`AgUiSuspension`): a resume entry naming
 *     its interrupt, or the tool message answering the frontend tool call it is
 *     waiting on. Any other tool result is refused — never folded in. A
 *     decision answering a consent gate's interrupt is named for the request
 *     that interrupt stands for (`answeringRequest`) — the page never sees the
 *     request id, and the matched interrupt is what binds its answer;
 *   - a frontend tool runs only when the app allow-listed its NAME — with the
 *     app's own description and schema, never the page's (a description the
 *     model reads is an instruction) — and only on a host that keeps the paused
 *     run until the page answers;
 *   - `state` and `context` reach the agent only through the app's validators;
 *     without one, a request carrying either is refused;
 *   - identity, credentials and redaction never come from a request: the host
 *     binds the thread to the caller the app authenticates (`ThreadBinder`).
 * `forwardedProps` is never read.
 */
import type { HeldConversation, PlanFacts, ProtocolPlan, ProtocolRequestFacts, ThreadBinding } from '../hosting/protocolAdapter.js';
import type { Tool } from '../tools/tools.js';
import type { AgUiMessage, AgUiResumeEntry, AgUiRunInput, AgUiSuspension } from './types.js';
/** The longest thread or run id read — longer is refused, never truncated. */
export declare const AG_UI_MAX_ID_LENGTH = 128;
/**
 * Read one AG-UI request body — its shape and its ids — refusing what the
 * protocol does not allow by the field's NAME, never by its value.
 *
 * @throws WireRequestRefusal (400, `ERR_INVALID_RUN_INPUT`)
 */
export declare function readAgUiRunInput(body: unknown): AgUiRunInput;
/**
 * What a request reader hands the core: the one turn a request asks for, in
 * AG-UI's terms. `AgUiRunInput` is one (a `RunAgentInput` as sent); a reader
 * for another body builds one from it — `tools` and `context` may be left out.
 *
 * It carries no identity, credential or redaction setting, and the core reads
 * nothing else a reader adds: the caller is bound by the host's `ThreadBinder`,
 * a credential reaches a run only through the host's `sealRequest`.
 */
export interface AgUiTurnRequest {
    /** The conversation the request NAMES — format-checked, never a key. */
    readonly threadId: string;
    /** The run id the stream names this run by — format-checked. */
    readonly runId: string;
    readonly parentRunId?: string;
    /**
     * The messages, newest last. Only the newest is read — a user message (the
     * run's message), or the `tool` message answering the frontend tool call a
     * paused run waits on. A system or developer message anywhere is refused.
     */
    readonly messages: readonly AgUiMessage[];
    /** The frontend tools the caller offers — run only when the app allow-listed the name. */
    readonly tools?: AgUiRunInput['tools'];
    /** Reaches the agent only through the app's `accept.context` validator. */
    readonly context?: AgUiRunInput['context'];
    /** Reaches the agent only through the app's `accept.state` validator. */
    readonly state?: unknown;
    /** Answers to the interrupt a paused run waits on — matched to the server's own record. */
    readonly resume?: readonly AgUiResumeEntry[];
}
/**
 * What a request reader is given: the request as the host read it — UNTRUSTED.
 * The host port's own `ProtocolRequestFacts` (the parsed body, the headers).
 */
export type AgUiRequestFacts = ProtocolRequestFacts;
/**
 * The request-reading strategy: a body → the turn it asks for. Mapping only;
 * every rule runs after it, in the core. Refuse a body it cannot read by
 * throwing a `WireRequestRefusal` (its status and code reach the caller);
 * anything else it throws is refused as a malformed request, in fixed words.
 *
 * @example A gateway that sends `{ conversationId, requestId, text }`
 * ```ts
 * const reader: AgUiRequestReader = ({ body }) => {
 *   const b = body as { conversationId?: unknown; requestId?: unknown; text?: unknown };
 *   return {
 *     threadId: String(b.conversationId),
 *     runId: String(b.requestId),
 *     messages: [{ id: 'gateway-turn', role: 'user', content: String(b.text) }],
 *   };
 * };
 * ```
 */
export type AgUiRequestReader = (request: AgUiRequestFacts) => AgUiTurnRequest;
/** The default reader: the body IS an AG-UI `RunAgentInput`. */
export declare const runAgentInputReader: AgUiRequestReader;
/**
 * The core's read of one request: `reader` maps the body, and what it produced
 * is checked by {@link readAgUiRunInput} — whichever reader it was. A custom
 * reader's answer is copied as plain JSON first; the default reader's is the
 * parsed body itself, read exactly as before readers were replaceable.
 *
 * @throws WireRequestRefusal — the reader's own refusal, or the core's by name
 *   (400, `ERR_INVALID_RUN_INPUT`).
 */
export declare function readAgUiRequest(reader: AgUiRequestReader, request: AgUiRequestFacts): AgUiRunInput;
/** What a page's `state` or `context` is checked by before the agent may see it. */
export type AgUiValidator = (value: unknown, at: {
    /** The conversation the request was bound to — whose state this claims to be. */
    readonly thread?: ThreadBinding;
    readonly headers: Readonly<Record<string, string>>;
}) => unknown;
/** The rules one adapter plans by — built from `agUi()`'s options. */
export interface AgUiTurnRules {
    /** The frontend tools the app allow-listed, by name: each builds the tool the agent is given. */
    readonly frontendTools: ReadonlyMap<string, () => Tool>;
    readonly accept: {
        readonly state?: AgUiValidator;
        readonly context?: AgUiValidator;
    };
}
/**
 * Plan one turn: the request (read by {@link readAgUiRunInput}) against what
 * the server holds for its bound conversation.
 *
 * @throws WireRequestRefusal — by name, for everything a page may not decide.
 */
export declare function planAgUiTurn(input: AgUiRunInput, held: HeldConversation, facts: PlanFacts, rules: AgUiTurnRules): ProtocolPlan;
/**
 * A stored suspension record, checked — the store holds bytes; a record that
 * is not one this adapter wrote is `undefined`, and nothing is matched to it.
 */
export declare function readAgUiSuspension(value: unknown): AgUiSuspension | undefined;
//# sourceMappingURL=request.d.ts.map