UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

93 lines (92 loc) • 6.36 kB
import type { PeerInboundChainRef } from "../../agents/peer-admission.js"; import { type SafeNotifier } from "../safe-notify.js"; import { type NotificationInjectionOutcome, type PendingSessionNotifications, type SystemInjectionPriority, type TaskNotificationPayload } from "../task-notification.js"; import type { PushQueue } from "../push-queue.js"; import type { TaskEvent, TaskSpec } from "../types.js"; import type { Stats } from "./assemble-result.js"; import type { CaptureOptOutRef, LiveHandle, ManualCompactRef, McpRedialRef, NotificationLaneBindings, NotifyRef, Prepared, RunInternals, RunnerDepsSeat, TaskIdRef } from "./contracts.js"; export interface RunIdentityWiringInput { /** borrowed-readonly — the task spec: the task id and the memory / notification seats it names. */ spec: TaskSpec; /** borrowed-mutable — the run's event queue: the manifest, roster-delta, compaction_outcome and redelivered * task_notification frames. */ queue: PushQueue<TaskEvent>; /** borrowed-mutable — the leg's prepared seat: the harness sinks (`onUndrainedEngineNotes`, `engineInjectionsHeld`, * `onUndrainedUserInputs`, `onEngineNoteConsumed`) are installed, `nextTurn` is appended to; the ids, the identity * envelope, the hold refs, the memory session and the listing / roster faces are read. */ prepared: Prepared; /** borrowed-readonly — the trusted run-scoped channel: `parentToolCallId`, `onNotifyInjectorReady`. */ internals: RunInternals | undefined; /** borrowed-mutable — the stream layer's backstop carrier: the memory scopes, the edited-files reader and the * owed delegation terminal are published here the moment they exist. */ taskIdRef: TaskIdRef | undefined; /** borrowed-readonly — the stream layer's readiness callback, fired ONCE with the live-task handle. */ onReady: (handle: LiveHandle) => void; /** borrowed-mutable — the manual /compact seat: its mooted-frame channel is installed here. */ manualCompactRef: ManualCompactRef; /** borrowed-mutable — the notify() bridge: `inject` is bound here (absent on the public path). */ notifyRef: NotifyRef | undefined; /** borrowed-mutable — the capture opt-out bridge: `flip` is bound here when a memory session mounted. */ captureOptOutRef: CaptureOptOutRef | undefined; /** borrowed-mutable — the MCP re-dial bridge: `redial` is bound here when the leg declared MCP servers. */ mcpRedialRef: McpRedialRef | undefined; /** borrowed-readonly — the notification lane's ONE injection entry (the R0 lane's). */ injectTaskNotification: (notification: TaskNotificationPayload, opts?: { priority?: SystemInjectionPriority; }) => Promise<NotificationInjectionOutcome>; /** borrowed-mutable — the turn-open dedup set (the cross-layer double-park dedup): a redelivered frame's key is registered here. */ deliveredAtTurnOpen: Set<string>; /** borrowed-mutable — the peer inbound chain, overwritten by each consumed peer-class payload. */ peerInboundChainRef: PeerInboundChainRef; /** borrowed-mutable — the notification lane's bindings seat (its own `let`s behind getters / setters, never a copy): * this lane binds the harness, the session anchor and the identity mint the lane's closures read, and reads the * anchor back in the undrained-notes sink. */ notificationLane: NotificationLaneBindings; /** borrowed-mutable — the Runner's per-session parked-notification store: drained at turn open, re-pended on failure. */ pendingSessionNotifications: PendingSessionNotifications; /** borrowed-readonly — the Runner's deployment deps, read LIVE (`onDelegationLifecycle`, `onNotice`). */ runner: RunnerDepsSeat; } export interface RunIdentityWiringResult { /** The run's canonical task id (`spec.taskId ?? sessionId`) — one source, shared with `ident()`. */ runSourceTaskId: string; /** The spawning tool call's id when this task runs AS A SUB-AGENT; undefined on a top-level run. */ parentToolCallId: string | undefined; /** The event-identity mint: a fresh eventId per event, plus the sub-agent attribution when there is one. */ ident: () => { eventId: string; parentToolCallId?: string; sourceTaskId?: string; }; /** The delegation-lifecycle emission closure both stations share (spawn here, terminal in the driver). */ emitDelegationLifecycle: (event: import("../types.js").DelegationLifecycleEvent) => void; /** The loop-liveness latch and the two attribution seats (ended / userInterrupted / userHalted). */ loopLatch: { ended: boolean; userInterrupted: boolean; userHalted: boolean; }; /** This leg's usage counters, zeroed here; the harness-handlers lane is their writer from the first turn on. */ stats: Stats; /** The held agent_end account, a READ FACE over this lane's own `let` (the undrained-inputs sink writes it * when the run committed a durable park); the terminal-adoption lane settles it minus what the park carried. */ undrainedUserAtEnd: { readonly current: { steer: number; followUp: number; } | undefined; }; /** The run's ONE isolation scope for the {@link RunInternals} observation sinks: minted here because * the manifest sink below is the run's first call into one, and handed on to the harness-handlers lane * so its activity beats are contained by the SAME account — bounded disclosure is per notifier, so a * second scope would report one broken sink twice and count it in two places. */ internalsNotifier: SafeNotifier; /** Did the run END with a person's steer / follow-up still pending (queued, or drained at the final boundary and * never served)? A READ FACE over this lane's own `let`, written by the same undrained-inputs sink on BOTH its arms * (park or not): the terminal-adoption lane folds it into the answer-settled verdict — a "stop" answer the person had * already asked to continue past is not a settled answer, so a stop that cut that continuation is a stop on work. */ userInputLostAtEnd: { readonly current: boolean; }; } export declare function runIdentityWiring(input: RunIdentityWiringInput): RunIdentityWiringResult;