/**
 * Asking the USER a structured question, and waiting for the answer.
 *
 * `awaitApproval` collects a yes/no about work already proposed; this collects the scope BEFORE the
 * work. Two surfaces produce it — a configured intake (`AgentLoopDeps.intake`) and the model-callable
 * `ask` tool (`AgentLoopDeps.ask`) — and they deliberately produce the SAME {@link
 * ElicitationRequest}, persist through the same tool-call row, and resume through the same
 * `tool:<runId>:<callId>` signal. A consumer cannot tell which one asked, and should not have to.
 */
import type { StandardSchemaV1 } from '@standard-schema/spec';
import { type ElicitationInput } from './elicitation-input.js';
import type { Decision, ToolDefinition } from './types.js';
/**
 * Whatever a human sent into a parked run. One channel carries both, because a question set is
 * persisted as a `pending_approval` action so it lands in the approvals inbox a deployment already
 * has — which means an operator pressing Approve there delivers a {@link Decision} to a run that is
 * waiting on answers. The loop reduces one to the other; see {@link normalizeElicitationReply}.
 */
export type HumanReply = Decision | ElicitationReply;
/**
 * Thrown when a reply is the wrong shape for the wait it was delivered to: answers to a question
 * set, addressed to a tool call that is waiting on an approve/reject.
 *
 * Refused rather than reduced, because there is no honest reduction in that direction. A yes/no can
 * be read as "confirmed the pre-picked answers" (see {@link normalizeElicitationReply}); a set of
 * answers says nothing at all about whether the proposed work should go ahead, and reading its
 * absent `approved` as `false` would record a rejection the person never made.
 */
export declare class HumanReplyMismatchError extends Error {
    readonly runId: string;
    readonly toolCallId: string;
    constructor(runId: string, toolCallId: string);
}
/**
 * Is this a human's yes/no {@link Decision}, rather than answers to a question set? Structural
 * rather than by class: both shapes are plain JSON off an HTTP body by the time they arrive, and
 * `approved` is the only field a `Decision` carries.
 */
export declare function isHumanDecision(reply: HumanReply): reply is Decision;
/** One choice a question offers. */
export interface ElicitationOption {
    /** Stable identifier submitted back. Never shown to the user. */
    value: string;
    /** What the user reads. */
    label: string;
    /**
     * A single character a UI may bind as a keyboard shortcut for this option. Advisory — nothing in
     * the library reads it, and a client is free to render its own.
     */
    hotkey?: string;
}
/** One question in a set. */
export interface ElicitationQuestion {
    /** Unique within its request; the key answers come back under. */
    id: string;
    prompt: string;
    /** A line of help under the prompt. */
    description?: string;
    /**
     * The choices. Required unless {@link input} asks for a typed value — then optional, and a UI may
     * offer them as suggestions. An `input` of type `select` still picks from these.
     */
    options?: ElicitationOption[];
    /**
     * Ask for a typed value (a number, a date, a sentence…) instead of — or, for `select`, on top of —
     * a pick from `options`. The answer is still a `string[]`, in the type's canonical form; see
     * `elicitation-input.ts`.
     */
    input?: ElicitationInput;
    /** More than one option may be chosen. Omit → single choice. */
    multiple?: boolean;
    /**
     * The options already picked for the user. The claim this whole surface makes is that confirming
     * is enough, so a question with no defaults is a question the user must stop and think about —
     * which is the case the design is trying to avoid. Empty/omitted is allowed and means exactly
     * that: submitting without answering leaves this question unanswered.
     */
    defaults?: string[];
    /** Accept values that are not among `options` (a typed-in answer). Omit → options only. */
    allowFreeText?: boolean;
}
/**
 * A question set awaiting a human. Identical in shape whether an `@Agent`'s configured intake or
 * the model's `ask` tool authored it — `source` records which, for audit, not for control flow.
 *
 * `questions.length` is known when the request is written, which is what lets a client render
 * "Question 1 of 3" without guessing whether a fourth is coming.
 */
export interface ElicitationRequest {
    /** The tool-call id this request is persisted under, and the signal it is answered through. */
    id: string;
    source: 'intake' | 'ask';
    /** What the assistant says above the form. */
    preamble?: string;
    questions: ElicitationQuestion[];
}
/** What a human sent back for an {@link ElicitationRequest}. */
export interface ElicitationReply {
    /**
     * questionId → chosen values. A question whose id is ABSENT takes the request's own `defaults` —
     * that is what makes "just submit" mean "yes, your pre-picked answers". A present-but-empty array
     * is an explicit "none of these" and does NOT fall back.
     */
    answers: Record<string, string[]>;
    /**
     * The user declined to answer and told the agent to proceed on its own assumptions. Distinct from
     * confirming the defaults even though the resulting values are the same: one is a decision the
     * user made, the other is one they refused to make, and only the first is evidence of intent.
     */
    skipped?: boolean;
    /** Opaque ref of WHO answered, when it wasn't the run's own actor. */
    answeredByRef?: string;
    /**
     * The surface the answer came through — `'web'`, `'slack'`, `'console'`, … — the counterpart of
     * an approval's `decidedVia`.
     */
    answeredVia?: string;
}
/** A settled elicitation: what the agent proceeds on, and how it got there. */
export interface ElicitationOutcome {
    /** One entry per question, in request order — always present, so a caller never re-applies defaults. */
    answers: Record<string, string[]>;
    skipped: boolean;
    /** Question ids filled from the request's `defaults` rather than by the human. */
    defaulted: string[];
    /**
     * Who answered (or skipped) — the reply's `answeredByRef` (the answering actor's id). The
     * counterpart of an approval's `decidedBy`. Absent when the reply did not say.
     */
    answeredBy?: string;
    /** The surface it came through (`'web'`, `'slack'`, …) — an approval's `decidedVia`. */
    answeredVia?: string;
}
/**
 * Read whatever the human channel delivered as an {@link ElicitationReply}.
 *
 * A question set is persisted as an `action` tool call in `pending_approval` — that is what puts it
 * in the approvals inbox a deployment already has, instead of needing one of its own. The cost of
 * that choice is that the thing which comes back may be a {@link Decision} someone pressed
 * Approve/Reject on rather than a set of answers, and a `Decision` carries no `answers` at all.
 *
 * Approve means every question keeps its own pre-picked `defaults`, which is exactly what "just
 * submit" already means on this surface; Reject is the same declining-to-answer a skip is. Neither
 * reading is a guess — a yes/no channel cannot say more than that, and saying it here is what lets
 * one inbox settle both kinds of pending work.
 *
 * Returns the reply UNCHANGED when it already carries answers, so the common path allocates nothing
 * and a caller can identity-compare.
 */
export declare function normalizeElicitationReply(reply: HumanReply): ElicitationReply;
/**
 * Settle a reply against the request it answers: fill every unanswered question from its own
 * `defaults`, drop submitted values that aren't on offer, and collapse a single-choice question to
 * one value.
 *
 * PURE, and deliberately so. Both of its inputs are already journaled by the time the loop calls it
 * — the request came from module config or from an `llm:<i>` checkpoint, the reply from the signal
 * checkpoint — so every process replaying the turn reaches the same values without a checkpoint of
 * its own. Resolving defaults in the HTTP layer instead would put them behind a store read that a
 * replay would have to repeat.
 */
export declare function resolveElicitation(args: {
    request: ElicitationRequest;
    reply: HumanReply;
}): ElicitationOutcome;
/**
 * What a settled elicitation looks like to everyone downstream: the model reading it back as a tool
 * result, the thread reader rendering it, the auditor asking what the agent was told to do. One
 * shape for both surfaces — nothing here records which of them asked.
 */
export interface ElicitationResult extends ElicitationOutcome {
    /** The questions against the chosen LABELS, so a reader (and a model) can act on it. */
    summary: string;
}
/** {@link resolveElicitation} plus its human-readable rendering. Pure, for the same reason. */
export declare function settleElicitation(args: {
    request: ElicitationRequest;
    reply: HumanReply;
}): ElicitationResult;
/**
 * The answers as the model reads them: the question's own prompt against the chosen options' LABELS,
 * not their opaque `value`s — a model shown `{"scope":["b"]}` has been told nothing.
 */
export declare function renderElicitationAnswers(args: {
    request: ElicitationRequest;
    outcome: ElicitationOutcome;
}): string;
/** The reserved tool name the model calls to ask the user something. */
export declare const ASK_TOOL_NAME = "ask";
/** What the model must supply when it calls `ask`. */
export interface AskToolInput {
    preamble?: string;
    questions: ElicitationQuestion[];
}
/** How many questions one `ask` may carry. A form the user has to scroll is a form they skip. */
export declare const MAX_ASK_QUESTIONS = 5;
/**
 * The `ask` tool's input schema, hand-written rather than borrowed from a validation library: core
 * depends on no validator, and the schema has to carry a JSON Schema a provider can constrain
 * generation against. It publishes one through the Standard JSON Schema extension
 * (`~standard.jsonSchema.input`), which is the path the AI SDK adapter already recognises for
 * Valibot / ArkType / Zod 4.
 */
export declare const askInputSchema: StandardSchemaV1<unknown, AskToolInput>;
/**
 * What the model is told the `ask` tool is for. Written to discourage the two failure modes that
 * make a clarifying question worse than a guess: asking about something the conversation already
 * settled, and asking without saying what you would have done.
 */
export declare const ASK_TOOL_DESCRIPTION = "Ask the user to settle the scope of the work before you do it. Use it when a reasonable person would produce a materially different result depending on the answer \u2014 not to confirm something the conversation already says. Every question must pre-pick the answer you would choose, so the user can confirm instead of deciding. The user may decline, in which case you proceed on those pre-picked answers.";
/**
 * The `ask` tool as the model sees it. NOT a `ToolSpec` and never registered: `ask` has no handler,
 * because the loop settles it against a human instead of invoking anything. Keeping it out of the
 * `ToolRegistry` is also what keeps the kind decision off a process-local lookup — see
 * `claimToolCall`.
 */
export declare function askToolDefinition(): ToolDefinition;
/** A question set an `@Agent` asks before it starts working. See `AgentLoopDeps.intake`. */
export interface AgentIntake {
    questions: ElicitationQuestion[];
    /** What the assistant says above the form. Omit → {@link DEFAULT_INTAKE_PREAMBLE}. */
    preamble?: string;
    /**
     * `'thread-start'` (default) asks once, on the first turn of a thread; `'every-turn'` asks before
     * every turn. Both are decided from what `load:thread` recorded about the thread when the turn
     * began, never from anything this process happens to know — by the time a replay reaches the
     * question, the thread already holds the assistant message the first attempt wrote.
     */
    when?: 'thread-start' | 'every-turn';
}
export declare const DEFAULT_INTAKE_PREAMBLE = "A few questions before I start. I have pre-picked what I would choose, so confirming is enough.";
//# sourceMappingURL=elicitation.d.ts.map