@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
90 lines • 4.75 kB
TypeScript
import { type DetectorSpec, type Finding, type GuardContext, type GuardrailAction, type GuardrailRule, type GuardrailStage, type Segment } from './types.js';
import { Vault } from './vault.js';
/**
* One reported hit. `values` holds the distinct matched values so a caller can fingerprint them
* (a keyed hash correlates repeats without storing the value) — never persist them as they are.
*/
export interface GuardHit {
ruleId: string;
ruleName: string;
action: GuardrailAction;
detector: string;
category: string;
score: number;
count: number;
/** Distinct values found (at most 20). In-memory only. */
values: string[];
/** Found in the newest turn (false: only in re-sent history, already reported once). */
fresh: boolean;
/** `detector_error` hits: what failed, and what the rule's fail mode made of it. */
error?: string;
failMode?: 'open' | 'closed';
}
export interface ScanResult {
stage: GuardrailStage;
/** Most severe action among the rules that fired. */
action: GuardrailAction;
/** The rule that decided a block / approval, and the message for the person. */
decisive?: {
id: string;
name: string;
message: string;
};
/** Segment texts after redaction (same order as the input). */
segments: string[];
/** Whether any segment changed. */
changed: boolean;
hits: GuardHit[];
vault: Vault;
/** Redacted spans. */
redactions: number;
latencyMs: number;
}
export interface ScanOptions {
/** Per-stage refusal messages, for rules that set none. */
messages?: Partial<Record<GuardrailStage, string>>;
/** Refusal message for `approve`, for rules that set none. */
approvalMessage?: string;
/**
* Stages whose redactions are reversible (unless the rule sets `restore: false`). Default
* `['llm_request']`: what the caller sent is theirs to get back; what a tool or the model produced
* is removed one-way. A caller whose tool results are its own data may add `tool_result`.
*/
restorableStages?: readonly GuardrailStage[];
}
export declare const DEFAULT_MESSAGES: Record<GuardrailStage, string>;
export declare const DEFAULT_APPROVAL_MESSAGE = "This needs approval under your organization's AI guardrails before it can go ahead.";
/** What replaces an instruction-like finding: it is removed, not tokenized. */
export declare const INJECTION_REPLACEMENT = "[removed: suspected prompt injection]";
/** Whether a rule's scope covers the context (stage, tool, `when`). Segments are filtered apart. */
export declare function ruleApplies<C extends GuardContext>(rule: GuardrailRule<C>, ctx: C): boolean;
export declare function orderRules<C extends GuardContext>(rules: readonly GuardrailRule<C>[]): GuardrailRule<C>[];
/** Runs one detector on one text. A custom detector's throw is the rule's fail mode to decide. */
export declare function runDetector<C extends GuardContext>(spec: DetectorSpec<C>, text: string, ctx: C): Promise<Finding[]>;
/**
* The in-process detectors of a rule set, as one span locator — what a stream window must never
* cut through (see `StreamGuard`'s `locate`). Custom detectors are left out: they may be remote.
*/
export declare function spanLocator<C extends GuardContext>(rules: readonly GuardrailRule<C>[]): ((text: string) => Finding[]) | undefined;
/**
* Non-overlapping spans. Overlapping findings are merged into their union (nothing that any
* detector found is left uncovered), labelled by the longer finding (ties: the higher score) —
* an injected HTML comment that contains an email address is removed as a whole. With `text`, a
* merged span's value is re-read from it.
*/
export declare function resolveOverlaps(findings: readonly Finding[], text?: string): Finding[];
export declare function applyRedactions(text: string, findings: readonly Finding[], vault: Vault, restorable: boolean): {
text: string;
count: number;
};
/**
* Evaluates the rules for one stage over a set of segments. Rules run by ascending priority; an
* `allow` rule that fires stops evaluation; otherwise every firing rule contributes and the most
* severe action wins (block > approve > redact > log). Detector results are shared between rules.
*
* Blocking applies to the NEWEST turn: content found only in re-sent history (`fresh: false`) was
* already refused once, so it is removed one-way instead — the conversation can go on and the value
* still never reaches the model.
*/
export declare function scan<C extends GuardContext>(rules: readonly GuardrailRule<C>[], ctx: C, segments: readonly Segment[], vault?: Vault, options?: ScanOptions): Promise<ScanResult>;
//# sourceMappingURL=engine.d.ts.map