import { type ChannelAdapterContext } from "#channel/adapter.js"; import { type ContextContainer } from "#context/container.js"; import { type DurableSession, type DurableSessionState } from "#execution/durable-session-store.js"; import { type HarnessModelMessage } from "#harness/messages.js"; import type { HandleEventFn, HarnessSession, HarnessSessionBase } from "#harness/types.js"; import { type MessageStreamEvent, type UnstampedMessageStreamEvent } from "#protocol/message.js"; import { type SessionProjection } from "#protocol/session-projection.js"; /** * Whose event a session publishes. Every event reaches the channel adapter, the * session stream, and stream-event hooks. The session's own events also reach * its instrumentation and carry its turn's delivery ids. * * A relayed event belongs to an exchange this session carries for a child * session or a workflow run: the question or sign-in it raised, the turn * boundary that question causes here, and the `input.resolved` for the answer * this session routes back. This session's instrumentation never tracks that * pending input, so no event of the exchange reaches it; the child records its * side as its own. */ export type SessionEventOrigin = "own" | "relayed"; /** The session a step publishes to: its stream and the state it starts from. */ export interface SessionStepState { readonly serializedContext: Record; readonly sessionState: DurableSessionState; readonly sessionWritable: WritableStream; } /** A {@link SessionStepState} with the conversation history, for a step that reads or changes it. */ export interface SessionHistoryStepState extends SessionStepState { readonly history: HarnessModelMessage[]; } /** The context and session state a publication leaves behind. */ export interface PublishedSessionEvents { readonly serializedContext: Record; readonly sessionState: DurableSessionState; } /** * Publishes a session step's own events, such as a workflow tool's * `action.partial`, exactly as a turn publishes its events. Call from a step * and adopt the result: hooks run in the session's context and may change it. */ export declare function publishSessionEvents(target: SessionStepState, events: readonly UnstampedMessageStreamEvent[]): Promise; /** Publishes events of an exchange this session relays; see {@link SessionEventOrigin}. */ export declare function relaySessionEvents(target: SessionStepState, events: readonly UnstampedMessageStreamEvent[]): Promise; /** A session step's context and session, restored so the step can publish. */ export interface RestoredSessionStep { readonly ctx: ContextContainer; readonly durableSession: DurableSession; readonly sessionWritable: WritableStream; } /** A {@link RestoredSessionStep} with the history, so its publication sees a whole session. */ export interface RestoredSessionHistoryStep extends RestoredSessionStep { readonly history: HarnessModelMessage[]; } export declare function restoreSessionStep(step: SessionStepState): Promise; /** * What a session step publishes, and how it changes the session the * publication leaves. `S` is a {@link HarnessSession} only for a step * restored with its history. */ export interface SessionStepPublication { readonly origin: SessionEventOrigin; /** Where a relayed input batch came from; the channel adapter and its forwarding see it. */ readonly inputSource?: string; /** Emits the step's events in the session's context scope. */ publish(emit: HandleEventFn, session: S): Promise; /** * Changes the step makes to the session once the scope has committed it, * before its continuation token is reconciled. */ updateSession?(session: S, published: T): SessionUpdate; } /** The session a step keeps, and anything it derived while changing it. */ export interface SessionUpdate { readonly session: S; readonly result?: R; } /** * Publishes from a step that owns the session. Returns the context and session * state to adopt, and the result of `updateSession`. `step.ctx` is updated in place. * The history is published and returned only when the step was restored with it. */ export declare function publishFromSessionStep(step: RestoredSessionHistoryStep, publication: SessionStepPublication): Promise<{ readonly published: PublishedSessionEvents & { readonly history: HarnessModelMessage[]; }; readonly result: R | undefined; }>; export declare function publishFromSessionStep(step: RestoredSessionStep, publication: SessionStepPublication): Promise<{ readonly published: PublishedSessionEvents; readonly result: R | undefined; }>; /** * Holds a session's stream for one step, which keeps its writer lock until it * releases it. Events reach the stream through `SessionEventPublisher.emit`. */ export interface SessionEventWriter { /** Closes the session stream; only a terminal event (`done`, completion, or failure) does this. */ close(): Promise; /** Releases the writer lock so the next step can acquire it. Safe after `close()`. */ release(): void; } /** Dispatches a session's events to its channel and stream-event hooks. */ export interface SessionEventDispatcher { /** The context delivery hands the channel adapter; a turn step also hands it to `adapter.deliver`. */ readonly adapterCtx: ChannelAdapterContext; /** * Runs the stream-event hooks for a written event. Only a turn step passes * `cancelTurn`; see `turn-event-handler.ts`. */ runHooks(event: MessageStreamEvent, cancelTurn?: () => void): Promise; } /** A session's stream held by one step, with the dispatch of the events that step publishes. */ export interface SessionEventPublisher { readonly dispatcher: SessionEventDispatcher; readonly writer: SessionEventWriter; /** * Delivers and writes one event the step produced, and returns it * as written for its hooks. Delivery comes first so the channel adapter's * handler shapes what is written. */ emit(event: UnstampedMessageStreamEvent): Promise; /** `emit`, then the event's stream-event hooks. */ publish(event: UnstampedMessageStreamEvent): Promise; } export declare function openSessionEventPublisher(input: { readonly ctx: ContextContainer; readonly origin: SessionEventOrigin; readonly sessionWritable: WritableStream; readonly inputSource?: string; }): SessionEventPublisher; /** The session's projection as of the last event it published. */ export declare function readSessionProjection(ctx: ContextContainer): SessionProjection; type TerminalSessionEvent = Extract; /** * Publishes a terminal `session.completed` or `session.failed` from outside a * turn as the session's own event, through its channel adapter and * instrumentation, then closes the session stream so readers following it * reach EOF. Stream-event hooks do not run: the ending session may not * restore, and no turn scope remains for authored code. Never throws. * * When the context cannot be restored, the event is only stamped, written, and * the stream closed: the one degraded write of a session event. */ export declare function publishTerminalSessionEvent(input: { readonly errorId?: string; readonly event: TerminalSessionEvent; readonly serializedContext: Record; readonly sessionWritable: WritableStream; /** The session's last turn, for channel handlers' `ctx.session.turn`. */ readonly turn?: { readonly id: string; readonly sequence: number; }; /** The turn the event ends, for instrumentation. */ readonly turnId?: string; }): Promise; export {};