import type { StandardSchemaV1 } from '@standard-schema/spec';
import type { RolesPolicy } from './spi/roles-policy.js';
import type { AiToolCtx, ToolDescribeScope, ToolHandler, ToolInputPreview, ToolInputPreviewScope, ToolPreflightResult } from './spi/tool.js';
import type { Actor, ToolDefinition, ToolSpec } from './types.js';
/** Thrown when an actor invokes a tool their role is not allowed. */
export declare class ToolForbiddenError extends Error {
    readonly toolName: string;
    constructor(toolName: string);
}
/**
 * Thrown when a registered tool is invoked while this deployment has it turned off (`enabled` /
 * `isEnabled()`). Distinct from {@link ToolForbiddenError}, which is about the actor, and from
 * {@link ToolNotFoundError}, which is about a name nobody registered — an operator reading a log
 * needs to tell "you flipped the flag" apart from "that tool does not exist in this build".
 *
 * Reachable in normal operation, not just from a forged call: a HITL `action` approved before the
 * flag was turned off runs its tool afterwards.
 */
export declare class ToolDisabledError extends Error {
    readonly toolName: string;
    constructor(toolName: string);
}
/** Thrown when a tool is invoked that was never registered. */
export declare class ToolNotFoundError extends Error {
    readonly toolName: string;
    constructor(toolName: string);
}
/** Thrown when a tool's input fails its Standard Schema validation. */
export declare class ToolInputInvalidError extends Error {
    readonly toolName: string;
    readonly issues: readonly StandardSchemaV1.Issue[];
    constructor(toolName: string, issues: readonly StandardSchemaV1.Issue[]);
}
export declare class ToolPreflightDeniedError extends Error {
    readonly toolName: string;
    readonly reason: string;
    constructor(toolName: string, reason: string);
}
/** Trusted preparation or a fresh schema parse changed the approved JSON input. */
export declare class ToolInputDriftError extends Error {
    readonly toolName: string;
    constructor(toolName: string);
}
/**
 * Holds every registered tool and gates invocation.
 *
 * Note: `definitionsFor` returns NEUTRAL definitions (no `execute`). The agent loop runs
 * each tool itself as a (durable) step — so even read tools are not auto-executed by the
 * model. `action` tools additionally require HITL approval before the loop runs them.
 */
export declare class ToolRegistry {
    private readonly entries;
    register(spec: ToolSpec, handler: ToolHandler): void;
    /**
     * Drop a tool, so it is neither offered to the model nor invocable. Returns whether there was one.
     *
     * For a tool whose EXISTENCE is not decided here: an MCP server may stop exporting a tool between
     * one `tools/list` and the next, and leaving the old spec registered would go on offering the
     * model a tool whose next call fails on somebody else's machine. Whoever registered a name is
     * responsible for deciding when it is gone — nothing in the registry itself expires.
     */
    unregister(name: string): boolean;
    has(name: string): boolean;
    hasPresentation(name: string): boolean;
    /** Used by a journaled already-completed preflight; never executes the domain handler. */
    presentResult(name: string, output: unknown, ctx: AiToolCtx): Promise<void>;
    /**
     * How a streamed call of `name` is previewed while its input arrives (`ToolHandler.previewInput`),
     * or `undefined`. A preview that fails to build is no preview: it never fails the turn.
     */
    previewInput(name: string, scope: ToolInputPreviewScope): Promise<ToolInputPreview | undefined>;
    spec(name: string): ToolSpec | undefined;
    allSpecs(): ToolSpec[];
    /**
     * The tools to offer the model for this actor+agent, after the four filter layers: what this
     * agent pinned, what this deployment has enabled, what this actor's role allows, and what each
     * tool's own `canUse` allows this actor.
     *
     * Every layer only ever removes tools, so no arrangement of them can widen what a turn reaches.
     * The allow-list goes FIRST, even though it is the narrowest statement: it is a pure name-set
     * match, while each of the three below it may be a round trip — an authz service, a feature-flag
     * store, an entitlement table — and this runs once per model step.
     */
    definitionsFor(actor: Actor, policy: RolesPolicy, allowedTools?: string[], scope?: Omit<ToolDescribeScope, 'actor'>): Promise<ToolDefinition[]>;
    /**
     * The specs {@link definitionsFor} offers the model, whole — the same four gates (allow-list,
     * enabled, role, `canUse`) in the same order. For a surface that lists what an actor can reach
     * (`GET <path>/tools`), which must never disagree with what the model is actually shown.
     */
    visibleSpecs(actor: Actor, policy: RolesPolicy, allowedTools?: string[]): Promise<ToolSpec[]>;
    private visibleEntries;
    /**
     * Run a tool. Re-checks that the tool is enabled, that the role allows it and that the tool's own
     * `canUse` admits the actor (defense-in-depth — a call can reach here from a replayed durable step
     * or an approval granted before the flag moved, neither of which went through `definitionsFor`
     * again) and re-parses the input. With `options.allowedTools` (the turn's persona allow-list) a
     * tool off that list is refused last, the same way the offer narrowed it. A tool whose
     * `describe()` answers `available: false` for the call's scope is refused as not registered.
     */
    private validated;
    prepare(name: string, input: unknown, ctx: AiToolCtx, policy: RolesPolicy, options?: PrepareOptions): Promise<ToolPreflightResult>;
    /** Expose the single schema parse; snapshotInput opts proposal callers into immutable JSON. */
    prepareValidated(name: string, input: unknown, ctx: AiToolCtx, policy: RolesPolicy, options?: PrepareOptions): Promise<ToolPreparationResult>;
    invoke(name: string, input: unknown, ctx: AiToolCtx, policy: RolesPolicy, options?: InvokeOptions): Promise<unknown>;
}
/** Per-call narrowing for {@link ToolRegistry.invoke}. */
export interface InvokeOptions {
    /**
     * Only these tool names may run — the turn's persona allow-list. Checked after `enabled`, the roles
     * policy and `canUse`. Undefined → no such check (every caller predating personas).
     */
    allowedTools?: readonly string[];
    /** Trusted normalized JSON input. Own-property presence requires comparison even if undefined. */
    approvedInput?: unknown;
}
export interface PrepareOptions extends InvokeOptions {
    /** Preserve a detached normalized JSON snapshot and refuse mutation by the prepare hook. */
    snapshotInput?: boolean;
}
export interface ToolPreparationResult {
    input: unknown;
    preflight: ToolPreflightResult;
}
/**
 * Default gate: one of the actor's roles must be in `spec.roles` (else the default roles). An empty
 * list means no restriction — the default: a tool is callable by whoever the actor resolver resolved,
 * an anonymous visitor included. `action` tools still park on approval regardless.
 */
export declare class DefaultRolesPolicy implements RolesPolicy {
    private readonly defaultRoles;
    private readonly emptyRoles;
    constructor(defaultRoles?: string[], options?: RolesPolicyOptions);
    can(actor: Actor, tool: ToolSpec): boolean;
}
/**
 * What an empty roles list means to {@link DefaultRolesPolicy}: `'allow'` (the default) — no
 * restriction; `'deny'` — nobody.
 */
export type EmptyRoles = 'allow' | 'deny';
export interface RolesPolicyOptions {
    /** What an empty roles list means. Default `'allow'`. */
    emptyRoles?: EmptyRoles;
}
/**
 * The closed gate — {@link DefaultRolesPolicy} with `emptyRoles: 'deny'`: the actor needs a role the
 * tool declares (else one of the default roles). A tool with no `roles` and no default roles, or with
 * an explicitly empty list, reaches nobody. For apps where an empty list means "no one" — a computed
 * `roles` that can come out empty, a multi-tenant MCP surface.
 */
export declare class ClosedRolesPolicy extends DefaultRolesPolicy {
    constructor(defaultRoles?: string[]);
}
//# sourceMappingURL=tool-registry.d.ts.map