@sema-agent/core
Version:
Stateless, task-oriented AI agent core
103 lines (102 loc) • 7.07 kB
TypeScript
/**
* The run body's TERMINAL ADOPTION (R14), verbatim from `Runner.runLocked`, between the leg's finally and
* the settle: the typed causes lifted over the leg's anonymous end (the brain-call guardrail's stall, the tool gate's own
* stop, the platform lane's external cause — which alone overrides a real throw), the usage ledger's FINAL charge with its
* slow-charge disclosure, the live-abort orphan reconcile and its synthetic `tool_end` frames, the held session-write
* drain, the user-interruption marker, the durable park's carried caller input and the held agent_end account's settle,
* the dropped post-compact announce disclosure, and the end-of-task compaction pass (`finish` — since S7 the lane's
* own module-private function, verbatim from the Runner's private method: the pass has one caller, and a sibling file would be a
* lane-to-lane reach, the S6 legs' reading).
*
* Async (six first-level awaits, the same awaits at the same positions). It ends by entering the settle lane (`next`) in
* its LAST continuation — the settle's first read sits on the tick `finish` resolved on, as it did in the one-function
* body — and returns what it returns. What crosses the boundary is exactly what the settle reads of this lane's work: the
* ADOPTED cause (`threw`, possibly lifted here) and the compaction outcome (`comp`); the pause / interruption / reconcile
* facts are consumed here.
*/
import type { AssistantMessage } from "../../internal/llm.js";
import type { Model } from "../../internal/llm.js";
import { type MaybeCompactOptions } from "../auto-compaction.js";
import type { SessionStore } from "../session.js";
import type { PushQueue } from "../push-queue.js";
import type { Brain, OwedUserInputAccount, TaskEvent, TaskSpec } from "../types.js";
import { type Stats } from "./assemble-result.js";
import type { EndOfTaskCompaction, Prepared, RunnerDepsSeat, RunState } from "./contracts.js";
export interface RunTerminalAdoptionInput<R> {
/** borrowed-readonly — the task spec: the task id the account's notices name; `finish`'s first argument (the end-of-task pass below). */
spec: TaskSpec;
/** borrowed-mutable — the run's event queue: the reconcile's synthetic `tool_end` frames and the end-of-task compaction's failure frame. */
queue: PushQueue<TaskEvent>;
/** borrowed-mutable — the leg's prepared seat: the guardrail / gate-stop / paused refs are read, the usage ledger charged, the session
* reconciled and the marker appended, the harness's parkable inputs read and dropped. */
prepared: Prepared;
/** borrowed-readonly — the run's mutable state: the platform terminal, the limit flags, the attachment state and the telemetry seat. */
rs: RunState;
/** borrowed-readonly — this leg's usage counters (the final charge's cumulative total). */
stats: Stats;
/** borrowed-readonly — the run's event-identity mint (the synthetic `tool_end` frames, the compaction failure frame). */
ident: () => {
eventId: string;
parentToolCallId?: string;
sourceTaskId?: string;
};
/** borrowed-readonly — the `message_committed` mint (the reconcile's appended toolResults, the marker). */
emitCommitted: (entryId: string, role: "user" | "assistant" | "toolResult", toolCallId?: string) => void;
/** borrowed-readonly — the observed tool-start ids the reconcile splits orphans by (EMPTIED by the reconcile's commit). */
startedToolCallIds: Set<string>;
/** borrowed-readonly — the label map the synthetic `tool_end` frames carry. */
toolLabels: Map<string, string>;
/** borrowed-readonly — the hard walltime timer: `fired` is one of the interruption facts. */
timeout: {
readonly fired: boolean;
};
/** borrowed-readonly — the compaction machinery's accounted brain (the end-of-task summary call is accounted too). */
compactionBrain: Brain;
/** borrowed-readonly — the shared compaction breaker: an open breaker skips the end-of-task attempt. */
compactionBreaker: {
readonly failures: number;
};
/** borrowed-readonly — the window-safety builder the end-of-task lane shares with the boundary / PTL lanes. */
windowSafetyOptions: (mainModel: Model) => Pick<MaybeCompactOptions, "fallbackBudget" | "onWindowSafety">;
/** borrowed-readonly — the held agent_end account, as the read face on the identity lane's Result. */
undrainedUserAtEnd: {
readonly current: {
steer: number;
followUp: number;
} | undefined;
};
/** borrowed-readonly — did the run end with a person's steer / follow-up still pending (the identity lane's read face)? Folded
* into the answer-settled verdict this lane evaluates once. */
userInputLostAtEnd: {
readonly current: boolean;
};
/** borrowed-readonly — the leg lane's final assistant message (its `stopReason` is one of the interruption facts). */
final: AssistantMessage | undefined;
/** borrowed-readonly — what the leg threw (undefined on a clean end); this lane may LIFT a typed cause over it and hands the adopted value on. */
threw: unknown;
/** borrowed-readonly — the live-abort flag the leg captured before its release-abort. */
abortedLive: boolean;
/** borrowed-readonly — the leg's snapshot of `loopLatch.userInterrupted` (gates the interruption marker). */
userInterruptedLive: boolean;
/** borrowed-readonly — the Runner's deployment deps, read LIVE (`onError`, `checkpointStore`, `onNotice`); the one home of why it is
* a seat and not a captured object is {@link RunnerDepsSeat}. */
runner: RunnerDepsSeat;
/** borrowed-readonly — the session store: the end-of-task pass touches the leg's session through it (`finish`'s teardown legs). */
sessions: SessionStore;
/** borrowed-readonly — the settle lane, entered in this lane's last continuation with the adopted cause and the compaction outcome. */
next: (adopted: RunTerminalAdoptionResult) => Promise<R>;
}
/** What the settle reads of this lane's work. */
export interface RunTerminalAdoptionResult {
/** The ADOPTED terminal cause: the leg's throw, or the typed cause lifted over it here (guardrail stall / gate stop / platform terminal). */
threw: unknown;
/** The end-of-task compaction pass's outcome. */
comp: EndOfTaskCompaction;
/** This lane's ONE evaluation of {@link answerSettled}: a clean `"stop"` final with no queued continuation lost. The
* settle lane hands it to the arbitration (`ResultFlags.answerSettled`), the teardown attribution and the notice. */
answerSettled: boolean;
/** The undrained-input account, UNSETTLED: this lane knows every fact but one — whether this leg's consumed
* checkpoint row comes back — and that one is the next lane's compensation to perform, not to predict. */
owedUserInput: OwedUserInputAccount;
}
export declare function runTerminalAdoption<R>(input: RunTerminalAdoptionInput<R>): Promise<R>;