@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
112 lines • 5.85 kB
TypeScript
import type { ToolConfirmation } from '../tool-presentation.js';
import type { Actor, ToolCallApproval, ToolCallStatus, ToolKind, ToolSpec } from '../types.js';
/** The approver that means "the person the run is acting for" — the thread's own actor. */
export declare const REQUESTER_APPROVER = "requester";
/** The tool a requirement is asked about. `spec` is absent where this process cannot resolve it. */
export interface ApprovalToolRef {
name: string;
kind: ToolKind;
spec?: ToolSpec;
}
/** Where the call is being made. */
export interface ApprovalThreadRef {
threadId: string;
runId: string;
agentName?: string;
}
/**
* What an action tool call needs before it runs.
*
* - `required: false` → the call runs without asking anyone (it is still recorded as an action).
* - `approver` → who may decide: {@link REQUESTER_APPROVER} (the thread's own actor — the default)
* or any other string, which the default {@link ApprovalPolicy.canDecide} reads as a ROLE the
* decider must hold. Streamed on `approval-requested` and persisted on the call.
* - `ttlMs` → how long the request stays open. When it lapses the call settles `expired` and the
* model is told nobody approved it. Absent → it waits indefinitely.
*/
export interface ApprovalRequirement {
required: boolean;
approver: string;
ttlMs?: number;
}
/** A decision about to be taken on a call, as {@link ApprovalPolicy.canDecide} sees it. */
export interface ApprovalDecisionRef {
toolCallId: string;
/** The approver recorded on the call when it was put to a person. */
approver: string;
/** The actorRef the run is acting for — the owner of the call's thread. */
requesterRef: string;
}
/**
* Who has to approve an action tool call, and for how long the request stays open.
*
* Consulted by the LOOP once per `action` call, inside the call's `persist:toolcall` checkpoint — so
* a durable run reads the answer back on every replay instead of re-deciding it against a policy
* that may have changed while it was parked. Only `action` calls are asked about: a policy cannot
* put a `read` behind an approval, and an `ask` (a question set) is always the requester's.
*/
export interface ApprovalPolicy {
requirementFor(tool: ApprovalToolRef, actor: Actor, thread: ApprovalThreadRef): ApprovalRequirement | Promise<ApprovalRequirement>;
/**
* May `actor` settle this call? Checked by the approve/reject routes before a decision is
* signalled. Absent → {@link defaultCanDecide}: the requester approver means the thread's own
* actor, anything else is a role the actor must hold. Plug an authz Gate here for abilities.
*/
canDecide?(actor: Actor, decision: ApprovalDecisionRef): boolean | Promise<boolean>;
}
/**
* The shorthand `config/agent.ts` takes instead of a whole {@link ApprovalPolicy}: who decides and
* for how long, for every `action` call — or per tool, by name. `approvalPolicy: { ttlMs: 900_000 }`
* expires every request after 15 minutes; `{ tools: { refund: { approver: 'admin' } } }` routes
* refunds to admins and leaves every other action with the requester.
*/
export interface ApprovalRules {
/** Who decides by default: `'requester'` (the default) or a role name. */
approver?: string;
/** How long a request stays open by default, in ms. Omit → it never lapses. */
ttlMs?: number;
/** Per-tool overrides. `required: false` runs that action without asking anyone. */
tools?: Record<string, Partial<ApprovalRequirement>>;
}
/** An {@link ApprovalPolicy} built from {@link ApprovalRules}. */
export declare function approvalRules(rules: ApprovalRules): ApprovalPolicy;
/** Accept either a whole policy or the {@link ApprovalRules} shorthand. */
export declare function toApprovalPolicy(value: ApprovalPolicy | ApprovalRules): ApprovalPolicy;
/**
* The behaviour the lib always had: every `action` call waits on the person who asked, with no
* expiry.
*/
export declare class DefaultApprovalPolicy implements ApprovalPolicy {
requirementFor(tool: ApprovalToolRef): ApprovalRequirement;
}
/** The default decider rule — see {@link ApprovalPolicy.canDecide}. */
export declare function defaultCanDecide(actor: Actor, decision: ApprovalDecisionRef): boolean;
/** Resolve whether `actor` may decide, through the policy's own rule when it has one. */
export declare function mayDecideApproval(policy: ApprovalPolicy | undefined, actor: Actor, decision: ApprovalDecisionRef): Promise<boolean>;
/** The columns a store keeps for one call's approval, however it names them. */
export interface ToolCallApprovalColumns {
proposalId?: string | undefined;
confirmation?: ToolConfirmation | undefined;
toolCallId: string;
status: ToolCallStatus;
approver: string | null | undefined;
expiresAt: string | Date | null | undefined;
remember: boolean | null | undefined;
executedByRef: string | null | undefined;
decidedVia: string | null | undefined;
error: string | null | undefined;
}
/** What the approve/reject routes need to know about a call before they signal a decision on it. */
export interface ToolCallApprovalState {
status: ToolCallStatus;
/** `null` for a call no policy put to anyone (an `ask`, or a row written before approvers existed). */
approver: string | null;
expiresAt: string | null;
}
/**
* Read a tool-call row back as the {@link ToolCallApproval} a thread carries, or `null` for a call
* no policy put to anyone (no approver recorded). Shared by every store so they agree on the
* status mapping: a call that ran — or ran and failed — after a decision was APPROVED.
*/
export declare function toolCallApprovalFromRow(row: ToolCallApprovalColumns): ToolCallApproval | null;
//# sourceMappingURL=approval-policy.d.ts.map