@sema-agent/core
Version:
Stateless, task-oriented AI agent core
71 lines (70 loc) • 4.35 kB
TypeScript
import { type AutoModeDecider } from "./auto-mode.js";
import { type AutoModeArmingRecipe, type AutoModeRebuildRefusal } from "./auto-mode-arming.js";
import type { Message } from "../internal/llm.js";
/** The redeeming deployment's FRESH model leg: one tool-less completion over a prompt CORE assembles.
* The split is the trust gate's: rules reach the prompt only through the recipe (a deployment-authored
* object), never through the leg — the leg dispatches, it does not compose. */
export type AutoModeClassifierCompletion = (call: {
systemPrompt: string;
userPrompt: string;
}, signal?: AbortSignal) => Promise<string>;
export interface AutoModeRebuildOptions {
/** The recipe read off the parked chain entry (`ConstraintChainEntryMeta.autoModeArming`). */
recorded: unknown;
/** The redeeming deployment's CURRENT auto-mode settings, minted with `autoModeArmingRecipeOf` from
* its own face. REQUIRED: bound ② is "the rebuilt arming is bounded by the settings in force", and a
* caller that declares none has put nothing in force — see {@link foldAutoModeArming}. A deployment
* with no overrides of its own still declares that (an empty face mints a bare recipe). */
current: unknown;
/** The fresh model leg. */
complete: AutoModeClassifierCompletion;
/**
* The transcript the classifier judges the action IN CONTEXT of — the REDEEMING leg's own messages,
* read at classify time (the window is rebuilt per classification, exactly as the live arming does).
*
* REQUIRED, and the reason is a permissiveness one rather than a quality one: the 207 process judges an
* action against the run that produced it (session linking, earlier writes), so a classifier handed no
* history can allow what the same classifier would block having seen it — and the empty window renders
* an affirmative claim, "this is the run's first gated action", that would simply be false. A provider
* that returns `[]` is DECLARING the transcript empty, which is a different statement from an engine
* that silently had none to show. A provider that throws fails the classification closed
* (`unavailable` ⇒ on to a person where the station has an approval seat, refused with a sentence that says
* so where it has none), never into a blind verdict.
*/
transcript: () => readonly Message[] | Promise<readonly Message[]>;
}
export type AutoModeRebuildResult = {
ok: true;
/** A decider carrying the ancestor's criteria, over the caller's model leg. */
decider: AutoModeDecider;
/**
* The RECORDED recipe, canonical — put THIS back on the re-supplied chain entry
* (`parentConstraints[].autoMode.arming`) so the constraint-chain digest matches the parked row.
* Deliberately not `effective`: the digest binds what the ANCESTOR recorded, and a local tighten
* must not read as a different ancestor chain.
*/
arming: AutoModeArmingRecipe;
/** What the rebuilt decider actually runs under (the tighten-only fold of recorded ∧ current). */
effective: AutoModeArmingRecipe;
/** True iff the current settings pulled a knob in. */
tightened: boolean;
} | {
ok: false;
reason: AutoModeRebuildRefusal;
message: string;
};
/**
* Rebuild a decider with a PARKED ancestor's criteria from its recorded recipe plus a fresh model leg.
*
* What is reproduced: the assembled system prompt (`buildAutoModePrompt` over the recorded rule
* overrides / settings-deny rules / session context, plus the engine's cross-session lane rule when
* the recipe says the arming leg spliced it), the transcript-window bounds and the round-trip
* timeout — i.e. every input the ancestor's own `createAutoModeDecider` call had except the model leg.
* A decider carries no state between rounds, so there is no ancestor state to reproduce or to withhold.
*
* NOT reproduced: this build's PROMPT ASSETS are its own. The recipe records the deployment's
* overrides, so the assembled prompt is checked against the digest the arming recorded — a fleet running
* two asset versions refuses to rebuild rather than enforce a different set of default rules under the
* ancestor's name.
*/
export declare function rebuildAutoModeDecider(opts: AutoModeRebuildOptions): AutoModeRebuildResult;