@sema-agent/core
Version:
Stateless, task-oriented AI agent core
75 lines (74 loc) • 4.16 kB
TypeScript
/**
* The gate's reading of `tool.check`: the ONE comparison of an answer with the verdict standing where it was raised, and the
* raise over every chain a leg's gate is constrained by (its own bus, then each inherited installation), read by that one
* comparison. The lanes own the raise points and what each reading does to the pass; this module owns what an answer means.
*/
import type { PermissionResult, ToolCallRequest } from "./tool-policy.js";
import type { AllowRuleShadow } from "./allow-rule-shadow.js";
import { type InstallationAskSettlement, type ToolCheckOutcome, type ToolCheckProjection } from "./mods/stations.js";
/** A verdict `tool.check` is raised over — never a deny (a standing refusal raises nothing). */
export type ToolCheckStanding = Exclude<PermissionResult, {
action: "deny";
}>;
/** What a reading came to. `minted` on an ask: the reading minted it over an allow (the ask carries no stamp of the round yet).
* `approved`: a person an inherited installation's question went to approved an edit of the call — the gate's approved-edit
* pass takes it, as it takes an edit approved at this leg's own question. */
export type ToolCheckReading = {
readonly kind: "stands";
} | {
readonly kind: "denied";
readonly deny: PermissionResult;
} | {
readonly kind: "asked";
readonly ask: Extract<PermissionResult, {
action: "ask";
}>;
readonly minted: boolean;
readonly marked?: true;
} | {
readonly kind: "cleared";
readonly allow: Extract<PermissionResult, {
action: "allow";
}>;
} | {
readonly kind: "shadowed";
readonly shadows: readonly AllowRuleShadow[];
} | {
readonly kind: "approved";
readonly allow: Extract<PermissionResult, {
action: "allow";
}> & {
readonly updatedInput: unknown;
};
readonly outstanding?: Extract<PermissionResult, {
action: "ask";
}>;
};
/** The call a reading is about: its wire name, the args the check judged, the policy's rewrite riding a minted verdict, and the
* request an inherited installation's question is settled over (the judged args). */
export interface ToolCheckCall {
readonly toolName: string;
readonly judged: unknown;
readonly rewrite: unknown;
readonly request: ToolCallRequest;
readonly signal: AbortSignal | undefined;
}
/** One chain a gate raises `tool.check` on: its raise over a projection; for the leg's own bus only, the allow layer's
* predicate under which its `allow` may clear an ask; for an inherited installation only, the settlement its question takes. */
export interface ToolCheckChain {
readonly raise: (projection: ToolCheckProjection) => Promise<ToolCheckOutcome | undefined>;
readonly mayClear?: () => boolean;
readonly settle?: InstallationAskSettlement;
}
/**
* The raise over every chain the leg's gate is constrained by, read by the one comparison: the leg's own bus first (its `allow`
* may clear an ask where the allow layer may), then each inherited installation in order (its `allow` clears nothing — a
* constraint only tightens). Each chain is raised over the verdict the previous left standing (`project`); a refusal ends it.
* An inherited installation's `ask` is its own question, settled where its installation froze (`settle`, the settlement its
* `classic.PreToolUse` ask takes in the fold): refused ⇒ refused; approved ⇒ the verdict standing before it stands (this leg's
* own question, if any, is still this leg's); approved with an edit ⇒ `approved`, for the gate's approved-edit pass; floated
* (the call marked for the park) ⇒ asked. The reading of the whole is the last verdict the chains moved the call to — an ask
* keeps the disclosures any later `allow` made over it — else the disclosures alone, else it stands. Undefined when no chain
* raised (nothing hangs on the event).
*/
export declare function readToolChecks(chains: readonly ToolCheckChain[], standing: ToolCheckStanding, call: ToolCheckCall, project: (current: ToolCheckStanding, mayClear: (() => boolean) | undefined) => ToolCheckProjection): Promise<ToolCheckReading | undefined>;