UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

128 lines (127 loc) • 10.5 kB
/** * 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;