@sema-agent/core
Version:
Stateless, task-oriented AI agent core
128 lines (127 loc) • 10.5 kB
TypeScript
/**
* PrepareTask's DELEGATION-SURFACE phase, verbatim from the driver: the surface's two doors
* (the background/workflow door the read/kill faces keep; the delegated-child arm SendMessage additionally mounts
* on), the TaskOutput / TaskStop mounts, the SendMessage mount with its tier-3 revival spawner and peer seats, the
* AgentTranscript residual lane, the peer lane's ListAgents, the Monitor tool, the EnterWorktree / ExitWorktree pair
* with the worktree session seat it seeds from the checkpoint or the workspace snapshot, and the offload reader. The
* revival spawner and the continuation tier it yields are machinery below (send-message-continuation.ts). The
* interface is the dependency list the segment had implicitly.
*
* SYNCHRONOUS FUNCTION, SYNCHRONOUS CALL: the stretch has no await, so the phase adds no yield between the hands
* mount before it and the question-face phase after it (a stretch with no await is extracted as
* a sync function). Read-stability of the host handles for the call: {@link RunInternals}
* (`@contract prepare.deps-read-stable`).
*
* The roster (`tools`) is borrowed-mutable here — the writer table lives on {@link Prepared.tools};
* this phase's rows are the eight mounts named above. `childPolicy` is NOT a seat yet: the
* delegation carriers still ride the enriched ctx's individual clamp fields, as they did in the driver.
*/
import type { AgentTool, ExecutionEnv, WorkspaceState } from "../../internal/harness.js";
import { type PeerLaneRefs } from "../../agents/peer-session-drain.js";
import type { SubagentRetainLedger } from "../../agents/retain-ledger.js";
import type { ShellReadAdmission } from "../../tools/fs/shell-read-check.js";
import { type WorktreeSessionRef } from "../../tools/worktree.js";
import type { CwdRef } from "../../tools/fs/index.js";
import { type ToolResultStore } from "../tool-result-store.js";
import type { RunnerDeps, TaskSpec, ToolEffect, ToolExecuteContext } from "../types.js";
import type { PrepareResume, RunInternals, RunnerSelfSeat, ToolFaceSnapshot } from "./contracts.js";
import { RosterBuilder } from "../tool-roster.js";
export interface PrepareDelegationSurfaceInput {
/** borrowed-readonly — the REBOUND spec. Read: `tools` (the shadow checks and the revival spawner's delegation-tool
* lookup), `oneShot` (the read/kill faces' completion promises), `retainBackgroundProcesses` (the Monitor receipt),
* `handsReadOnly` is NOT read here (the hands mount decided the surface). Never mutated. */
spec: Pick<TaskSpec, "tools" | "oneShot" | "retainBackgroundProcesses" | "excludeAllTools">;
/** borrowed-readonly — the deployment seats the mounts read: `workflowRunStore` / `backgroundAgentStore` / `mailboxStore` (the
* read/kill faces and the tier-3 revival seams), `rosterStore`, `peerLane`, `peerDirectory`, `onNotice`,
* `onBackgroundChildEvent`, `tracer`. */
deps: Pick<RunnerDeps, "workflowRunStore" | "backgroundAgentStore" | "mailboxStore" | "rosterStore" | "peerLane" | "peerDirectory" | "principalInboxConsumer" | "onNotice" | "onBackgroundChildEvent" | "tracer">;
/** borrowed-readonly — the trusted spawn-side channel: `parentNotify` (the delegated-child door), the uplink / sibling /
* identity seats the SendMessage mount forwards, `onTaskNotification`, `onSubagentSpawn`. Never mutated. */
internals: Pick<RunInternals, "parentNotify" | "parentPeerRef" | "uplinkSessionId" | "parentRetainLedger" | "explicitAgentName" | "parentTaskId" | "parentSessionId" | "peerSelfRef" | "peerInboundChainRef" | "onTaskNotification" | "onSubagentSpawn"> | undefined;
/** borrowed-readonly — the resume leg, or undefined: `seed.activeWorktree` seeds the worktree session (checkpoint first). */
resume: Pick<PrepareResume, "seed"> | undefined;
/** borrowed-readonly — the acquired session id (the mounts' session axis). */
sessionId: string;
/** borrowed-readonly — the per-task identity (the mounts' owner axis). */
hostTaskId: string;
/** borrowed-readonly — the registry scope the mounts register in. */
taskScope: string;
/** borrowed-readonly — the SETTLED task root (the worktree tools' repoRoot). */
taskRootFinal: string;
/** borrowed-readonly — the settled root in the CANONICAL spelling every fence judges with (the root-receiving
* point resolves it once). The Monitor mount's reset target: the shell tool is built with this same value, so
* a dead-cwd self-heal lands both tools on one directory rather than two spellings of it. */
taskRootCanonical: string;
/** borrowed-readonly — the run's resolved env the Monitor and worktree tools operate. */
executionEnv: ExecutionEnv;
/** borrowed-readonly — the trusted Runner self-reference the SendMessage / AgentTranscript mounts execute through; undefined
* when prepareTask runs standalone (then neither mounts). */
runnerSelf: RunnerSelfSeat | undefined;
/** borrowed-readonly — the background/workflow door's first half: the hands mount decided a real shell with write hands. */
backgroundTaskToolsActive: boolean;
/** borrowed-readonly — this run's shell read station's pre-spawn ADMISSION (declared at the hands phase), for `Monitor`: the only P11 face that spawns a shell command. */
shellReadAdmission: ShellReadAdmission | undefined;
/** borrowed-readonly — the door's second half: the Workflow tool is on the roster. */
workflowToolsActive: boolean;
/** borrowed-readonly — the peer lane's mount verdict for this leg. */
peerLaneActive: boolean;
/** borrowed-readonly — whether the BUILT-IN SendMessage is on this face (the ListAgents mount's second term). */
peerSendMessageBuiltIn: boolean;
/** borrowed-mutable — the lane's late-bound facts; the SendMessage mount hands the SAME object to its peer seats (identity is
* the contract: the wiring station fills `askEffective` later). Not written here. */
peerLaneRefs: PeerLaneRefs;
/** borrowed-readonly — the session-box drain's mount judgment (the `ReadInbox` door: a box drained by this leg). */ sessionBox?: import("../task-notification.js").SessionBoxBinding | undefined;
/** borrowed-mutable — the run's roster builder (`Prepared.tools` is its read face; the writer table is on that field).
* Writers here: the eight mounts (TaskOutput, TaskStop, SendMessage, AgentTranscript, ListAgents, Monitor, the worktree
* pair, the offload reader), every one a `mount`. */
roster: RosterBuilder;
/** borrowed-mutable — the effect collection (`Prepared.toolEffects`). Writers here: TaskOutput → read, TaskStop / SendMessage
* (built-in mount only) / Monitor / EnterWorktree / ExitWorktree → write. */
toolEffects: Map<string, ToolEffect>;
/** borrowed-mutable — the explicit-negative axis declarations. Writer here: the built-in SendMessage mount's `egress: false`
* (report-face only). */
axisExplicitNegatives: Map<string, {
irreversible?: false;
egress?: false;
}>;
/** borrowed-mutable — the env-hand tool-name set the read posture reads. Writers here: Monitor and the two worktree tools
* (membership minted at the mount). */
envHandToolNames: Set<string>;
/** borrowed-readonly — the frozen tool-face snapshot (`exclude` feeds the ListAgents mount predicate). */
toolFaceSnapshot: Pick<ToolFaceSnapshot, "selector">;
/** borrowed-readonly — the large-result wrapper for first-party mounts. */
firstPartyOffload: (tool: AgentTool) => AgentTool;
/** borrowed-readonly — the run's offload store, or undefined when offload is disabled (then no reader mounts and the
* read/kill faces spill nowhere). */
offloadStore: ToolResultStore | undefined;
/** borrowed-readonly — the retain ledger the SendMessage mount continues children through (absent ⇒ honest not-retained). */
subagentRetain: SubagentRetainLedger | undefined;
/** borrowed-readonly — the caller-tool ctx enrichment: the revival spawner re-enters the delegation tool through it, and
* the SendMessage / AgentTranscript mounts activate their ctx-first arms with it. */
enrichSpecToolCtx: (ctx: ToolExecuteContext) => ToolExecuteContext;
/** borrowed-readonly — the seat this run hands its children (`checkpointSeatOf`); the background-agent read faces read a parked agent's approval card through it. */ checkpointSeat: import("../checkpoint-seat.js").CheckpointSeat | undefined;
/** borrowed-mutable — the hands mount's tracked-cwd seat: present ⇔ real shell + write hands; the worktree pair's mount
* predicate. Not written by this phase, but the tools it mounts over it ARE its writers: EnterWorktree and
* ExitWorktree assign `current` at run time (the hands band's shared cwd then points at the worktree, and back); the
* Monitor only reads it. The cell must stay the hands mount's own object — a copy would strand those writes. */
handsCwdRef: CwdRef | undefined;
/** borrowed-readonly — the workspace-state snapshot (the worktree seed's continuation rung), or undefined. */
wsSnapshot: Pick<WorkspaceState, "activeWorktree"> | undefined;
/** borrowed-readonly — the rebase of a snapshot path onto this leg's root. */
rebaseWsPath: (p: string) => string;
/** borrowed-readonly — the rebase of a checkpoint path onto this leg's root. */
rebaseRestoredPath: (p: string) => string;
/** borrowed-mutable — the workspace-state settle seat; the worktree mount stamps `restoredWorktreeDir` on it once. */
workspaceStateSettle: {
restoredWorktreeDir?: string;
} | undefined;
}
export interface PrepareDelegationSurfaceResult {
/** owned — whether the background/workflow door is open (TaskOutput / TaskStop / AgentTranscript ride it). */
delegationSurfaceActive: boolean;
/** borrowed-mutable — the EnterWorktree session's shared serializable state (`Prepared.worktreeSessionRef`), minted iff the
* worktree pair mounted. Writers: the worktree tools at run time (Enter/Exit); the suspend serializer reads it. */
worktreeSessionRef: WorktreeSessionRef | undefined;
}
/** The M6 phase body — prepareTask's delegation-surface stretch, verbatim (see the module header). */
export declare function prepareDelegationSurface(input: PrepareDelegationSurfaceInput): PrepareDelegationSurfaceResult;