@sema-agent/core
Version:
Stateless, task-oriented AI agent core
58 lines (57 loc) • 3.38 kB
TypeScript
/**
* The ONE exit for an auto-mode classification that could not RULE (`unavailable`: the classifier leg failed, or its
* per-level budget ran out) — shared by both classifier stations, the leg's gate and an ancestor's frozen classifier
* in the policy fold, so the rule is written once.
*
* ONE fork, on the APPROVAL SEAT (does an ask this station hands on reach a person — a live approver, or a durable
* park): with one, the ask goes on, its text saying why auto mode is asking, and a person decides; without one, the
* call is refused with CC's `x1t` sentence and the classification's FORM (`unavailable`) is attested on the deny. The seat is
* the only input to the fork — not the cause, not the mode. The handed-on ask carries `requiresRealApproval`: no
* automatic lane may answer it in the classifier's stead — not a blanket `onAsk:"allow"`, not the sandbox admission, not a
* budget resolver over its park (the park mints the non-budgetable kind). CC refuses either way; asking where a person can be
* asked is a declared departure (a classifier that is slow or down must not turn an attended session into a string
* of refusals). Neither arm is a block: the denial limit counts classifier RULINGS, and a person's refusal of the
* handed-on ask is a person's, not the classifier's.
*
* The observer hears every such classification with where the call went, except while the call is being aborted — a halt,
* or the run's end (the classifier did not fail; the call ended). It is observe-only: a throw never changes the arm.
*/
import { type AutoModeClassifierRound, type AutoModeUnavailableCause } from "./auto-mode.js";
import { type PermissionResult, type ToolCallRequest } from "./tool-policy.js";
/** Where an `unavailable` classification sent the call: `asked` = on to the approval seat, `denied` = refused. */
export type ClassifierUnavailableDisposition = "asked" | "denied";
/** What the stations' observer receives — the facts the `classifier.unavailable` notice is composed from. */
export interface ClassifierUnavailableInfo {
toolName: string;
toolCallId: string;
cause: AutoModeUnavailableCause;
disposition: ClassifierUnavailableDisposition;
}
export type ClassifierUnavailableObserver = (info: ClassifierUnavailableInfo) => void;
/** The station's two facts for the fork: whether an ask it hands on reaches a person (`true` only — anything else is
* no seat), and who hears it. */
export interface ClassifierUnavailableSeat {
approvalSeat?: boolean;
onUnavailable?: ClassifierUnavailableObserver;
}
/** The arm the fork chose: the ask to hand on, or the refusal. */
export type ClassifierUnavailableArm<A> = {
kind: "asked";
ask: A;
} | {
kind: "denied";
deny: PermissionResult;
};
export declare function classifierUnavailableArm<A extends Extract<PermissionResult, {
action: "ask";
}>>(args: {
ask: A;
req: ToolCallRequest;
cause: AutoModeUnavailableCause;
/** The ladder's attribution, for the refusal's sentence (it names both rungs when the ladder moved). */
attribution?: AutoModeClassifierRound;
seat: ClassifierUnavailableSeat | undefined;
/** The call is being aborted (its per-call signal — a halt, or the run's end): the observer is not told (the arm is chosen
* as ever). */
aborted: boolean;
}): ClassifierUnavailableArm<A>;