/** * Human-in-the-loop primitives. A gate pauses agent execution at a * named decision point and records an `Approval` in a user-supplied * `ApprovalStore`. When a human (or another automation) writes a * decision, any waiter resumes with that decision. * * The store can be in-memory for tests, SQLite for single-node * deployments, or a shared DB / queue for multi-worker setups. Any * store that implements the 3-method contract works. */ type ApprovalDecision = 'approved' | 'rejected'; interface Approval { id: string; /** Logical gate name (e.g. 'delete-user', 'send-email'). */ name: string; /** Caller-provided context for whoever reviews the approval. */ payload: TPayload; status: 'pending' | ApprovalDecision | 'cancelled'; createdAt: string; decidedAt?: string; /** Free-form metadata the approver attached (reason, user id, etc.). */ decisionMetadata?: Record; } interface ApprovalStore { /** Persist a new pending approval. */ put: (approval: Approval) => Promise; /** Read the current state of an approval. */ get: (id: string) => Promise | null>; /** Update status + metadata. */ patch: (id: string, update: Partial>) => Promise | null>; } interface RequestApprovalInput { /** Gate name (reuse across invocations — how approvers identify it). */ name: string; /** Context passed to reviewers. Safe to store — no secrets. */ payload: TPayload; /** Stable id for idempotent gating (e.g. tool call id). */ id: string; } interface ApprovalGate { /** * Reserve or reuse an approval by id. First caller creates a * `pending` record. Subsequent calls return the existing record * — perfect for resuming a crashed run. */ request: (input: RequestApprovalInput) => Promise>; /** * Wait for `approved` or `rejected`. Resolves immediately if the * approval is already decided. Polls at `pollMs` (default 500ms) * up to `timeoutMs` (default Infinity). */ await: (id: string, options?: { timeoutMs?: number; pollMs?: number; signal?: AbortSignal; }) => Promise>; /** Approve, rejecting, or cancelling an approval. */ decide: (id: string, decision: ApprovalDecision, metadata?: Record) => Promise>; cancel: (id: string) => Promise>; } /** * Build an approval gate over any `ApprovalStore`. The core loop * couldn't be simpler — create-or-load + poll + patch — but having it * behind a stable contract lets you swap persistence without touching * agent code. */ declare function createApprovalGate(store: ApprovalStore): ApprovalGate; /** In-memory `ApprovalStore` — handy for tests and single-worker demos. */ declare function createInMemoryApprovalStore(): ApprovalStore; export { type Approval, type ApprovalDecision, type ApprovalGate, type ApprovalStore, type RequestApprovalInput, createApprovalGate, createInMemoryApprovalStore };