UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

78 lines (77 loc) • 4.87 kB
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[]>; /** * Whether {@link transcript} is a DELEGATED leg's (a sub-agent the engine started on another agent's behalf, forks * included — the checkpoint's `isDelegatedChild`). REQUIRED, and a boolean: a delegated leg's user lane is the launching * agent's words, which the window shows as that agent's (`[launching agent]`), never with user authority — so the * redeeming host states which transcript it hands over; "not stated" is not a reading of either (#1166). */ delegated: boolean; } 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;