/** * KHAELOR * File: src/agent/session-handle.ts * Description: KernelSession — the kernel's narrow handle onto the durable event log and bus. * * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai */ import { isDurableEvent } from "../session/index.js"; import type { DurableEvent, DurableEventInput, EphemeralEventInput, EventBus, } from "../session/index.js"; /** * What the agent layer needs from the Session Engine (ARCHITECTURE.md §4.1): * read the recorded durable stream and publish new events. Everything the * kernel "knows" is derived from `events()` — never from loop-local flags. */ export interface KernelSession { readonly sessionId: string; /** All durable events recorded so far, in seq order (replayed + live). */ events(): readonly DurableEvent[]; /** Append (write-ahead) + publish; returns the assigned envelope. */ publishDurable(input: DurableEventInput): DurableEvent; /** Fire-and-forget streaming deltas — never persisted. */ publishEphemeral(input: EphemeralEventInput): void; } export interface EventLogSessionOptions { sessionId: string; /** The session bus (write-ahead appender already attached by the composition root). */ bus: EventBus; /** Events replayed by `SessionLog.open()` — empty for a fresh session. */ replayed?: readonly DurableEvent[]; } /** * Default KernelSession: an in-memory seq-ordered view over the bus. * Durable events published by ANY producer (kernel, executor, permission * service) land here synchronously because the bus dispatches write-ahead * appended envelopes before `publishDurable` returns (EVENT_MODEL.md §5.2). */ export class EventLogSession implements KernelSession { readonly sessionId: string; readonly #bus: EventBus; readonly #events: DurableEvent[]; constructor(options: EventLogSessionOptions) { this.sessionId = options.sessionId; this.#bus = options.bus; this.#events = [...(options.replayed ?? [])]; this.#bus.onAny((event) => { if (isDurableEvent(event)) this.#events.push(event); }); } events(): readonly DurableEvent[] { return this.#events; } publishDurable(input: DurableEventInput): DurableEvent { return this.#bus.publishDurable(input); } publishEphemeral(input: EphemeralEventInput): void { this.#bus.publishEphemeral(input); } }