@sema-agent/core
Version:
Stateless, task-oriented AI agent core
132 lines (131 loc) • 6.45 kB
TypeScript
/**
* The registration form, the two seats, and the screen every registration passes before admission:
* shape, unique name, the seat × tier table, the `uses` declaration, and the `budgetMs` fallback.
*/
import { type ModBusSide, type ModEventName, type ModRegistrationTier, type ModSeat, type ModTier } from "./events.js";
import { type ModBudgetReading } from "./budget.js";
import type { ModEventPayload, ModFailureCause, ModMatcher, ModSkip } from "./site-rules.js";
/** The configuration refusal: a registration the kernel cannot take refuses the whole prepare. */
export declare const MODS_INVALID_CODE = "config.mods_invalid";
/** The notice an admission refusal becomes (the run goes on without the refused registration). */
export declare const MODS_REGISTRATION_REFUSED_CODE = "mods.registration_refused";
/** What a registration declares it will touch — the upper bound the kernel holds it to. */
export interface ModUses {
/** Events it hangs handlers on (names or `<prefix>.*`). */
readonly events: readonly string[];
/** `$` methods it calls (method event names). */
readonly calls: readonly string[];
}
/** Who raised a dispatch: a registration (through its `$`), or the engine (`{plugin: "engine", tier: "core"}`). */
export interface ModOrigin {
readonly plugin: string;
readonly tier: ModTier;
}
/** The engine's own origin; its `plugin` word is reserved (no registration may take it). */
export declare const ENGINE_ORIGIN: ModOrigin;
/** The facts `$.plugin` carries. */
export interface ModPluginFacts {
readonly name: string;
}
/** The part of `$` every bus gives; each side adds its methods (`$.<noun>.<method>`). */
export interface ModDollarBase {
readonly plugin: ModPluginFacts;
}
/** One entry of `next.trace`: a handler (or the core) that ran beneath, and how it ended. */
export interface ModTraceEntry {
readonly index: number;
readonly plugin: string;
readonly tier: ModTier;
readonly outcome: ModTraceOutcome;
readonly ms: number;
}
/** How a chain member ended (CC words). */
export declare const MOD_TRACE_OUTCOMES: readonly ["returned", "passed", "rejected", "caught", "expired", "kept", "skipped", "bypassed"];
export type ModTraceOutcome = (typeof MOD_TRACE_OUTCOMES)[number];
/** What a `.catch` reads off `next.error`. */
export interface ModCaughtError {
readonly kind: ModFailureCause;
readonly message?: string;
readonly budget: number;
}
/** The third argument of a handler: continue the chain, or jump (prepend / append only). */
export interface ModNext {
(e: ModEventPayload): Promise<unknown>;
to(e: ModEventPayload, tier: ModTier): Promise<unknown>;
readonly origin: ModOrigin;
readonly signal: AbortSignal;
/** What ran beneath this handler's last `next`. */
readonly trace: readonly ModTraceEntry[];
readonly budget: ModBudgetReading;
/** Present on a `.catch`'s `next` only. */
readonly error?: ModCaughtError;
/** Present on a `.catch`'s `next` only: whether the failed handler had called `next`. */
readonly called?: boolean;
}
export type ModHandler<D extends ModDollarBase = ModDollarBase> = ($: D, e: ModEventPayload, next: ModNext) => unknown;
export interface ModHandlerOptions<D extends ModDollarBase = ModDollarBase> {
/** Answers for the handler when it throws, runs out of budget or breaks the site's contract. */
readonly catch?: ModHandler<D>;
/** Watch only: a detached `e`, outside the chain, its answer refused and disclosed. */
readonly observe?: boolean;
}
/** `on(pattern, handler, options?)` or `on(pattern, matcher, handler, options?)`. */
export interface On<D extends ModDollarBase = ModDollarBase> {
(pattern: string, handler: ModHandler<D>, options?: ModHandlerOptions<D>): void;
(pattern: string, matcher: ModMatcher, handler: ModHandler<D>, options?: ModHandlerOptions<D>): void;
}
export interface ModRegistration<D extends ModDollarBase = ModDollarBase> {
/** Unique in the run; names the registration everywhere (origin, trace, disclosures, admission). */
readonly name: string;
/** Deployment seat: required. Task seat: absent or `user`. */
readonly tier?: ModRegistrationTier;
readonly uses: ModUses;
/** The host's provenance label, handed to admission as given. */
readonly provenance?: string;
/** Each handler's own time; default 10 000 ms. */
readonly budgetMs?: number;
readonly options?: unknown;
register(on: On<D>, options: unknown): void;
}
/** One admission result: mounted (with the patterns it actually hung) or refused (by whom, why). */
export type ModAdmissionRecord = {
readonly name: string;
readonly seat: ModSeat;
readonly tier: ModTier;
readonly events: readonly string[];
readonly observe?: readonly string[];
/** Judges skipped while this registration was judged (their failure or site violation), as the dispatch listed them. */
readonly skipped?: readonly ModSkip[];
} | {
readonly name: string;
readonly seat: ModSeat;
readonly tier: ModTier;
readonly refusedBy: string;
readonly reason: string;
};
/** The two seats as a bus receives them; a seat is a list of registrations or absent. Screened as untrusted input. */
export interface ModSeats<D extends ModDollarBase = ModDollarBase> {
readonly deployment?: readonly ModRegistration<D>[];
readonly task?: readonly ModRegistration<D>[];
}
/** A registration that passed the screen, in run order. */
export interface ScreenedRegistration<D extends ModDollarBase = ModDollarBase> {
readonly registration: ModRegistration<D>;
readonly name: string;
readonly seat: ModSeat;
readonly tier: ModRegistrationTier;
readonly budgetMs: number;
readonly uses: ModUses;
readonly provenance?: string;
readonly eventsBound: ReadonlySet<ModEventName>;
readonly callsBound: ReadonlySet<ModEventName>;
}
export declare function modsInvalid(message: string): Error & {
readonly code: string;
};
/**
* Screen both seats and put the registrations in run order: by tier, then deployment before task, then
* each seat's own order. Throws `config.mods_invalid` for anything the kernel cannot take; a bad
* `budgetMs` is reported and replaced by the default instead.
*/
export declare function screenModSeats<D extends ModDollarBase>(seats: ModSeats<D>, side: ModBusSide, report: (err: Error) => void): ScreenedRegistration<D>[];