import { AgentMiddleware } from "../contracts/middleware/middleware.contract.mjs"; import { HumanApprovalOptions } from "./contracts/human-approval.type.mjs"; //#region ../ai/src/human/human-approval.d.ts /** * Human-in-the-loop approval gate for an agent's tool calls — the * middleware behind `ai.human.approval(options)`. * * **Role.** Pauses *before a specific tool call* and routes it to a human * who can **approve** (run the real tool unchanged), **reject** (the model * sees a typed error and self-corrects), or **edit** (run the tool with * reviewer-replaced args). The dangerous subset is chosen by an * {@link import("./contracts").InterruptPolicy} (allowlist / denylist / * predicate); every other call passes through untouched. * * **One hook.** Declares only `tool.before`. On each tool dispatch it: * 1. evaluates the policy — not gated → returns `void`, the real tool runs; * 2. for a gated call, builds an {@link ApprovalRequest} and calls the * {@link import("./contracts").ApprovalHandler}; * 3. applies the returned {@link ApprovalDecision}: * - `approve` → returns `void`, the real tool runs; * - `reject` → short-circuits a failed `ToolInvokeResult` carrying an * {@link ApprovalRejectedError} (the reviewer's `reason` reaches the * model); * - `edit` → rewrites `ctx.request.input` to the reviewer's args and * returns `void`, so the real tool runs with the edited args (schema * validation still applies — bad edits surface as a tool error). * * **Durable mode.** When a `store` is configured and the handler throws * {@link InterruptSuspendedError} (after persisting the interrupt * out-of-band), the middleware catches its **own** sentinel and * short-circuits a failed result carrying it — so the caller reads * `result.error.interruptId` and later calls * `ai.human.resume(interruptId, decision)`. The middleware **never throws * out of the pipeline**: every outcome (skip, approve, reject, edit, * suspend) returns normally; only a *handler bug* (a non-sentinel throw) * propagates, and even then the agent dispatch funnels it onto * `result.error` — `execute()` still never throws. * * @param options - Policy, handler, optional durable store, optional name. * @returns An {@link AgentMiddleware} declaring a single `tool.before` hook. * * @example * const support = ai.agent({ * model, * tools: [refundCustomer], * middleware: [ * humanApproval({ * policy: { type: "allowlist", tools: ["refundCustomer"], tags: () => ["money"] }, * handler: async (req) => ui.prompt(req), // { type: "edit", args: { amount: 5 } } * }), * ], * }); */ declare function humanApproval(options: HumanApprovalOptions): AgentMiddleware; //#endregion export { humanApproval }; //# sourceMappingURL=human-approval.d.mts.map