/**
 * checkin — the evidence-carrying human-consent primitive.
 *
 * "OpenWorker-class agents check in; agentfootprint checks in WITH THE
 * RECEIPTS." A tool declares `checkIn` (see `Tool.checkIn` in `tools/tools.ts`); when
 * it trips, the tool-dispatch loop pauses BEFORE executing and surfaces a
 * {@link CheckInRequest} — a typed ask that carries an EVIDENCE PACK
 * ({@link CheckInEvidence}): what the tool will do, what context the run
 * consumed, which context drove the choice, and a compact run-so-far trail.
 * A human answers with {@link checkInApproved} / {@link checkInDeclined};
 * the {@link CheckInDecision} lands as a typed record.
 *
 * This is the LEAF that owns every check-in TYPE + the pure assembly logic.
 * It has one runtime import, the `lib/frozenCopy.ts` leaf (which reads only
 * footprintjs's dev-mode flag); the rest are type-only imports of the message
 * shape + the influence-core attribution unit — so it stays cheap to import
 * and trivial to unit-test. The pause plumbing lives in
 * `core/agent/stages/toolCalls.ts`; the events in `events/`; the store in
 * `recorders/core/CheckInRecorder.ts`.
 *
 * NOT a policy engine (the `PermissionChecker` in `provider-contract/types.ts` is
 * untouched, and runs BEFORE this gate) and NOT UI. This asks a person to
 * CONSENT, with the receipts attached.
 *
 * Pattern: Strategy (pluggable evidence assembler + driver scorer) + pure
 *          value types. Every value here survives `structuredClone` + JSON
 *          (checkpoint discipline) — no functions, no class instances.
 */
import type { ArtifactRef } from '../artifacts/types.js';
import type { LLMMessage } from '../provider-contract/types.js';
import type { AskComponent } from '../tools/askComponent.js';
import type { AttributionUnit } from '../influence-core/types.js';
/**
 * The typed pause payload for one check-in. Rides the existing pause
 * machinery: it becomes the checkpoint's `pauseData` and is surfaced on
 * surfaced on `RunnerPauseOutcome.checkIn` (`core/pause.ts`). JSON/clone-safe.
 */
export interface CheckInRequest {
    /**
     * Names this request: the id a decision quotes
     * (`checkInApproved({ request: outcome.checkIn, by })`). Minted when the run
     * paused, unique to this pause, and bound to the exact call that runs on
     * approval — the tool, {@link args}, the call id and the served party. A
     * decision for any other request, or for a call that changed after the ask,
     * is refused (`ResumeDecisionError`). An opaque fingerprint: it carries no
     * value from the run.
     */
    readonly id: string;
    /** The tool the agent wants to run (its name). */
    readonly tool: string;
    /**
     * The arguments the call will run with: the model's proposal, with any value
     * the inputs layer filled (a tool's `askOrAssume` `assume` rule) and any
     * before-tool middleware rewrite applied — what a person approves is what
     * runs.
     */
    readonly args: Readonly<Record<string, unknown>>;
    /**
     * The model's stated reasoning for THIS call, when the assistant turn
     * carried text alongside the tool call. Omitted when the turn was a bare
     * tool call with no content.
     */
    readonly intent?: string;
    /** The receipts riding the ask. */
    readonly evidence: CheckInEvidence;
    /**
     * Which REGISTERED screen component collects the decision (9.24.0) — the
     * tool's own declaration (`defineTool({ checkIn, checkInComponent })`),
     * carried onto the ask. Absent means what it always meant: the screen
     * renders the evidence pack as prose. The answer is a `CheckInDecision`
     * either way — the component changes how the question is asked, never
     * what the answer is.
     */
    readonly component?: AskComponent;
}
/**
 * The evidence pack — the "receipts". The `'minimal'` assembler fills only
 * {@link willDo} (zero cost); the `'standard'` assembler fills all four.
 */
export interface CheckInEvidence {
    /** Plain-words claim of what will happen: the tool description + the
     *  rendered arguments. Always present. */
    readonly willDo: string;
    /** What context this run consumed so far — one frame per context piece
     *  (system rules, the user task, prior tool results). Absent under the
     *  `'minimal'` assembler. */
    readonly read?: readonly CheckInContextFrame[];
    /** Which context drove THIS choice, ranked most-to-least. Produced by the
     *  configured {@link CheckInScorer} (default: a zero-LLM lexical scorer).
     *  Absent under the `'minimal'` assembler. */
    readonly drivers?: readonly CheckInDriver[];
    /** A compact grouped summary of the run so far. Absent under `'minimal'`. */
    readonly trail?: CheckInTrail;
}
/** One piece of context the run consumed — role/channel + a compact summary. */
export interface CheckInContextFrame {
    /** Origin group: `'system' | 'task' | 'result'`. */
    readonly channel: string;
    /** A short, truncated summary of the piece (never the full payload). */
    readonly summary: string;
}
/** One ranked driver — a context unit and how strongly it aligns with the pick. */
export interface CheckInDriver {
    /** The unit id (the citation, e.g. `'system-1'`). */
    readonly id: string;
    /** Origin group: `'system' | 'task' | 'result'`. */
    readonly channel: string;
    /** The unit text (quotable). */
    readonly text: string;
    /** Alignment score — higher means it drove the pick more. Scorer-defined
     *  units; compare within one request, not across scorers. */
    readonly score: number;
}
/** A compact grouped summary of the run so far. */
export interface CheckInTrail {
    /** Which ReAct iteration this check-in fired on. */
    readonly iteration: number;
    /** The tool calls already completed this run, oldest first. */
    readonly toolCalls: readonly {
        readonly name: string;
        readonly ok: boolean;
    }[];
    /** One-line human summary, e.g. `"3 tools run over 2 iterations"`. */
    readonly summary: string;
}
/**
 * The human's answer to a check-in — the record that lands. Produced by
 * {@link checkInApproved} / {@link checkInDeclined} and passed to
 * `agent.resume(checkpoint, decision)`. JSON/clone-safe.
 */
/**
 * What a person CHOSE, when the answer is a value rather than a yes or a no.
 *
 * The ask got its typed half in 9.24.0 — {@link AskComponent} names a registered
 * screen component and the props it renders with. The ANSWER never did: a
 * decision was `approved` plus a free-text `note`, so a picked row, a brushed
 * date range or a chosen option had to travel as PROSE for the model to parse
 * back out. That is the exact failure the typed ask exists to prevent, surviving
 * on the return leg.
 *
 * Deliberately shaped like the ask, for the same reasons:
 *   • `kind` is CONSUMER vocabulary — meaningful to whoever registered the
 *     component, opaque here. Never a type name from this library.
 *   • `value` is small inline JSON, because it rides the resume call and lands
 *     in the run's history. Anything large belongs behind {@link from}.
 *   • `from` is the artifact the choice was made AGAINST. A row id means
 *     nothing on its own; it means something in a dataset.
 *
 * ── Why `coverage` is here, and it is the field people skip ─────────────────
 * A person who filtered 5,000 rows to 3 and picked one has not chosen from
 * 5,000. Without this field that pick is indistinguishable from an informed
 * choice over the whole set, and the difference is the whole value of a human
 * in the loop. It is the same distinction `coverage()` draws for a tool —
 * what was checked, and what a clean answer does not rule out — applied to the
 * person, because on this turn the person IS the tool.
 *
 * Every field must survive `structuredClone`: a decision rides the checkpoint.
 */
export interface DecisionValue {
    /** Consumer vocabulary for what this value IS — e.g. `'row-choice'`. */
    readonly kind: string;
    /** The chosen value itself. JSON, clone-safe, small. */
    readonly value: unknown;
    /** The artifact the choice was made against, when there was one. */
    readonly from?: ArtifactRef;
    /**
     * What the person could actually see when they chose.
     *
     * `seen` of `total`, and the filter that narrowed it. A pick made over a
     * filtered view is a different fact from a pick made over everything, and
     * only the screen knows which happened.
     */
    readonly coverage?: {
        readonly seen: number;
        readonly total: number;
        readonly filter?: string;
    };
}
export interface CheckInDecision {
    /**
     * The request this decision answers — the paused request's `id`
     * (`CheckInRequest.id`, `MiddlewareAsk.id`). A resume refuses a decision for
     * any other request, and answers each request once (`ResumeDecisionError`).
     */
    readonly requestId: string;
    /** True to run the tool, false to decline it. */
    readonly approved: boolean;
    /**
     * Who decided (an operator id, an email, a queue name — your call). Recorded
     * as given: a claim, not proof. Authenticate the person before you build the
     * decision; the library binds WHICH request and WHAT call, never who.
     */
    readonly by: string;
    /** Optional note. On decline it is surfaced to the model so it can adapt. */
    readonly note?: string;
    /** When the decision was made (ms since epoch). */
    readonly at: number;
    /**
     * What they chose, when the answer was a value and not just a yes.
     *
     * Optional everywhere: a decision without one is byte-identical to every
     * earlier release, and a screen that only approves or declines never sets it.
     */
    readonly value?: DecisionValue;
}
/** Options for {@link checkInApproved} / {@link checkInDeclined}. */
export interface CheckInDecisionInput {
    /**
     * The paused request being answered — the one the person was shown:
     * `outcome.checkIn` or `outcome.ask` (`PendingAsk.checkIn` / `.ask` on a
     * hosted door). Only its `id` is read; the decision answers that request and
     * no other.
     */
    readonly request: {
        readonly id: string;
    };
    /** Who decided. Recorded as given — see {@link CheckInDecision.by}. */
    readonly by: string;
    /** Optional free-text note. */
    readonly note?: string;
    /** What was chosen, for an ask that wanted a value rather than a yes. */
    readonly value?: DecisionValue;
}
/**
 * Approve a pending check-in — the paused tool executes normally on resume.
 *
 * The decision names the request it answers (`request.id`), so it answers that
 * request once and no other: a resume refuses it on a different pause, on a
 * call that changed after the ask, or a second time (`ResumeDecisionError`).
 *
 * @throws TypeError when `request` is not a paused request (it has no `id`).
 *
 * @example
 *   const decision = checkInApproved({
 *     request: outcome.checkIn,
 *     by: 'alice@ops',
 *     note: 'verified with customer',
 *   });
 *   const final = await agent.resume(outcome.checkpoint, decision);
 */
export declare function checkInApproved(input: CheckInDecisionInput): CheckInDecision;
/**
 * Decline a pending check-in — the tool is NOT executed; the model receives
 * a `"declined by human: <note>"` tool result and adapts in-loop.
 *
 * A decline is an answer too: it names its request and spends it, so an
 * approval presented for the same request afterwards is refused.
 *
 * @throws TypeError when `request` is not a paused request (it has no `id`).
 *
 * @example
 *   const decision = checkInDeclined({
 *     request: outcome.checkIn,
 *     by: 'alice@ops',
 *     note: 'amount too high',
 *   });
 *   const final = await agent.resume(outcome.checkpoint, decision);
 */
export declare function checkInDeclined(input: CheckInDecisionInput): CheckInDecision;
/**
 * Type guard — is this resume input a {@link CheckInDecision}? Distinguishes
 * a check-in answer from a plain `askHuman` tool-result value. A decision
 * names its request: an object without a `requestId` is not one.
 */
export declare function isCheckInDecision(x: unknown): x is CheckInDecision;
/**
 * The SHAPE of a decision before it names a request — `approved` and `by`.
 * What tells "a decision that names no request" (refused by name, with the
 * migration) apart from "not a decision at all" (`DecisionRequiredError`).
 *
 * @internal
 */
export declare function looksLikeDecision(x: unknown): x is Omit<CheckInDecision, 'requestId'>;
/**
 * What the model reads for a call a person declined: the result the dispatch
 * loop records, and the host's notice for a declined call a failed run left
 * open (`hosting/answeredPause.ts`). Either way the call did not run.
 *
 * @internal
 */
export declare function declinedResult(note?: string): string;
/**
 * What a tool declares to demand a check-in. `'always'` trips on every call;
 * a predicate trips selectively (e.g. only high-value refunds). A predicate
 * that throws trips (fail toward asking the human — consequential actions
 * should not silently proceed on a buggy predicate).
 */
export type CheckInDemand<TArgs = Readonly<Record<string, unknown>>> = 'always' | ((args: TArgs, ctx: CheckInPredicateContext) => boolean);
/** Context handed to a {@link CheckInDemand} predicate. */
export interface CheckInPredicateContext {
    /** The current ReAct iteration. */
    readonly iteration: number;
    /** This tool invocation's id. */
    readonly toolCallId: string;
    /** The conversation so far (system, user, prior tool results). */
    readonly history: readonly LLMMessage[];
}
/**
 * Decide whether a tool's declared demand trips for this call. Returns false
 * when the tool declared no `checkIn` (backward-compatible: byte-identical
 * behavior for tools without the field).
 *
 * The ONE place a predicate is asked, at every door (the loop's gate, an
 * approved ask's resume). It is handed its OWN frozen copy of the arguments
 * (`lib/frozenCopy.ts`), never the object the tool runs with: a predicate
 * that writes into its argument — after a person approved the call, or after
 * answering "no check-in needed" for it — must not change what runs. The
 * write throws in strict code (and a predicate that throws trips) or is
 * ignored in sloppy code (in dev mode, one warning names the cause). A copy
 * the caller already shares with the call's other callbacks is handed on as
 * it is (`frozenView`). Arguments no copy can be made of trip the gate.
 */
export declare function shouldCheckIn(demand: CheckInDemand<Readonly<Record<string, unknown>>> | undefined, args: Readonly<Record<string, unknown>>, ctx: CheckInPredicateContext): boolean;
/** Input to a {@link CheckInScorer}. Mirrors `influence-core`'s attribution
 *  shape so an embedding-backed scorer (wrapping `explainChoice`) drops in. */
export interface CheckInScoreInput {
    /** The chosen tool. `text` is what gets scored (name + description + args). */
    readonly tool: {
        readonly name: string;
        readonly text: string;
    };
    /** The context units to rank against the tool. */
    readonly units: readonly AttributionUnit[];
    /** Abort signal for network-backed scorers. */
    readonly signal?: AbortSignal;
}
/**
 * Ranks context units by how strongly each drove one tool choice. The
 * DEFAULT is {@link lexicalDriverScorer} — deterministic, zero LLM, zero
 * network. Swap in a richer one via `.checkIn({ scorer })`, e.g. wrapping
 * `explainChoice` from `agentfootprint` with your own embedder.
 *
 * @example a semantic scorer
 *   const scorer: CheckInScorer = async ({ tool, units, signal }) => {
 *     const ex = await explainChoice({ tool, units, embedder, signal });
 *     return ex.units.map((u) => ({ id: u.id, channel: u.channel, text: u.text, score: u.score }));
 *   };
 */
export type CheckInScorer = (input: CheckInScoreInput) => readonly CheckInDriver[] | Promise<readonly CheckInDriver[]>;
/**
 * The default drivers scorer: deterministic Jaccard token overlap between
 * the tool text and each context unit. Zero LLM, zero network, structuredClone
 * -safe output. Ties keep input order (stable sort).
 */
export declare const lexicalDriverScorer: CheckInScorer;
/** Everything the assembler needs to build one evidence pack. */
export interface CheckInAssemblerInput {
    /** The chosen tool — `name` for citations, `description` for `willDo`. */
    readonly tool: {
        readonly name: string;
        readonly description: string;
    };
    /** The proposed arguments. */
    readonly args: Readonly<Record<string, unknown>>;
    /** The model's stated reasoning, if any (assistant-turn text). */
    readonly intent?: string;
    /** The ReAct iteration this check-in fired on. */
    readonly iteration: number;
    /** The conversation so far — the raw material for `read`, `drivers`, `trail`. */
    readonly history: readonly LLMMessage[];
    /** The scorer to rank `drivers` with. */
    readonly scorer: CheckInScorer;
    /** Abort signal threaded to the scorer. */
    readonly signal?: AbortSignal;
}
/**
 * Builds the evidence pack for one check-in. Two are built in
 * ({@link standardEvidenceAssembler}, {@link minimalEvidenceAssembler});
 * pass your own to `.checkIn({ evidence })` for full control.
 */
export type CheckInAssembler = (input: CheckInAssemblerInput) => CheckInEvidence | Promise<CheckInEvidence>;
/** Which built-in assembler to use, by name. */
export type EvidencePreset = 'minimal' | 'standard';
/**
 * Derive attribution units from the run-so-far conversation: system rules
 * (split into sentences), the user task, and prior tool results. These feed
 * BOTH `read` (as frames) and `drivers` (scored). Ids are unique + stable.
 */
export declare function unitsFromHistory(history: readonly LLMMessage[]): AttributionUnit[];
/**
 * The `'standard'` assembler — fills all four evidence fields. The `drivers`
 * ranking runs the configured scorer over the run-so-far context units; the
 * default scorer is deterministic and makes zero LLM/network calls.
 */
export declare const standardEvidenceAssembler: CheckInAssembler;
/** The `'minimal'` assembler — only `willDo`. Zero cost; no scorer call. */
export declare const minimalEvidenceAssembler: CheckInAssembler;
/** What `.checkIn({...})` accepts on the Agent builder. */
export interface CheckInBuilderOptions {
    /**
     * How much evidence rides the ask. `'standard'` (default) fills all four
     * fields; `'minimal'` fills only `willDo` (zero cost); or pass your own
     * {@link CheckInAssembler}.
     */
    readonly evidence?: EvidencePreset | CheckInAssembler;
    /**
     * The scorer that ranks `drivers`. Default {@link lexicalDriverScorer}
     * (deterministic, zero LLM). Only consulted by the `'standard'` assembler.
     */
    readonly scorer?: CheckInScorer;
}
/** The resolved config threaded into the tool-dispatch handler. */
export interface ResolvedCheckInConfig {
    readonly assembler: CheckInAssembler;
    readonly scorer: CheckInScorer;
}
/**
 * Resolve builder options (or nothing) into a runtime config. The default —
 * `standard` evidence + `lexicalDriverScorer` — makes a tool that declares
 * `checkIn` work even when the builder never called `.checkIn()`.
 */
export declare function resolveCheckInConfig(opts?: CheckInBuilderOptions): ResolvedCheckInConfig;
