Skip to content

RealtimeSession

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:240

Provider-agnostic realtime voice session core. Wires a RealtimeProviderAdapter’s tool calls to a Maelstrom instance: update_ui submits an intent and withholds its tool result until the resulting render settles (speak-after-render); get_ui_state answers immediately from a structural snapshot; get_capabilities answers immediately from the vessel capability catalog; render-settle events push a debounced, latest-wins grounding string; and every fact the session learns is published on RealtimeSession.events, which also feeds the onEvent sidechannel.

Concurrent update_ui calls (a model can emit a second while the first is still being applied — the natural way a voice UI corrects itself mid-request) use latest-wins queueing: if the instance rejects submitIntent with RequestInFlightError because a prior intent is still applying, the new call becomes the session’s single pending queued intent instead of being answered immediately. A call that was already queued when a newer one arrives is answered right away with a “superseded” result and dropped — only the most recent barge-in survives. Once the in-flight request settles, the queued intent is retried; because a settled command queue doesn’t guarantee the orchestrator is ready to accept a new intent, the retry can lose the race and is attempted a bounded number of times before the call is answered as busy instead of retried forever. The raw exception never reaches the adapter either way.

const session = new RealtimeSession({
adapter,
instance: {
submitIntent: (intent) =>
orchestrator
.processIntent(intent)
.then((r) => ({ userMessage: r.userMessage })),
waitForIdle: async () => {
await orchestrator.commandProcessor.waitForIdle();
},
waitForIdleResult: () => orchestrator.commandProcessor.waitForIdle(),
getStructuralSnapshot: () => orchestrator.getStructuralSnapshot(),
getCapabilitySnapshot: () => orchestrator.getCapabilitySnapshot(),
onSettled: (cb) => orchestrator.onSettled(cb),
},
// …other options…
});
await session.connect();
  • VoiceSession

new RealtimeSession(options): RealtimeSession

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:324

RealtimeSessionOptions

RealtimeSession

readonly memory: RealtimeSessionMemory

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:264

Recovery evidence retained independently of provider delivery. It may be shared with other sessions of the same Maelstrom session identity and outlives this one until RealtimeSession.dispose.

get events(): SessionEventSource

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:380

Every fact this session publishes: connection lifecycle, transcript and media evidence, tool calls and their results, update_ui recovery outcomes, timings and the opening claim. Delivery is synchronous and in publish order, with no replay, so read RealtimeSession.observations for current values. The stream lives as long as this session; a replacement session has its own.

SessionEventSource


get greetingState(): GreetingState

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:425

Retained fixed-greeting presentation lifecycle for this shared session. The value is initialized synchronously from coordinator proof and survives session recreation when that proof is terminal. It does not mirror provider activity, speech success, errors, transcripts, connection state, or turn mode. Subscribe to greeting_state for later retained changes.

GreetingState


get lastError(): unknown

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:466

The failure behind the most recent error state, if any. Cleared at the start of the next connect() attempt, but preserved by explicit disconnect() even after that method returns the public state to idle. Typed provider failures are RealtimeVoiceError — switch on .code for recovery UX. If subscription cleanup also fails, an AggregateError retains the provider failure first, followed by cleanup failures.

unknown


get observations(): VoiceObservationSource

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:385

Shared continuous observations. Reading or subscribing does not connect the provider.

VoiceObservationSource


get state(): VoiceSessionState

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:368

VoiceSessionState

VoiceSession.state


get turnControl(): AdapterTurnControl | undefined

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:454

Current adapter-owned manual turn control. It is exposed only after the adapter establishes manual mode and is read dynamically so adapter degradation or teardown can replace or remove the control safely.

AdapterTurnControl | undefined


get turnMode(): TurnMode

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:435

Retained turn-boundary mode, initially automatic. Speech-native adapters establish a clean automatic mode after connect succeeds; adapters emit turn_mode when they establish manual control or change mode. A failed reconnect does not synthesize a clean transition or clear this value.

TurnMode


get turnModeError(): unknown

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:445

Diagnostic from an attempted automatic mode that degraded to manual. Clean mode events and a successful speech-native reconnect clear it; a failed reconnect preserves it. This value is for generic recovery guidance only; consumers must not render it verbatim or serialize it into telemetry.

unknown

connect(): Promise<void>

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:483

Opens one provider connection. Re-entry from a live state is a no-op. A successful connection that emitted no turn_mode establishes clean automatic mode; a failed or stale attempt never synthesizes that fallback and rejects with the adapter failure. An eligible configured greeting moves to preparing synchronously before the provider handshake; retained terminal proof leaves it settled or skipped and skips greeting work. The connection generation owns both the greeting and connecting notifications: a synchronous disconnect from either notification stops before audio activation, adapter subscription, or provider connect. Audio activation still occurs synchronously inside this call, before the first await. Rejects once the session is disposed.

Promise<void>

VoiceSession.connect


disconnect(): Promise<void>

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:676

Invalidates connection ownership and removes local subscriptions and greeting work before awaiting provider cleanup. Whether provider cleanup resolves or rejects, coordinator proof restores the greeting to retryable pending or terminal settled, and the public state becomes idle. lastError is preserved. A single cleanup or provider failure is rethrown unchanged; multiple failures are reported together in an AggregateError.

Promise<void>

VoiceSession.disconnect


dispose(): Promise<void>

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:704

Retires this session for good. It starts RealtimeSession.disconnect, then detaches the shared memory, so requests that settle later no longer write recovery evidence from a retired session. Later connect() calls reject. Repeated calls retain the first disconnect’s result, including a rejection, without repeating provider teardown or lifecycle notifications.

Promise<void>


getAudioStreams(): AdapterAudioStreams

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:734

Live audio streams for UI metering (voice orbs, level meters). Delegates to the provider adapter; see AdapterAudioStreams for absence semantics.

AdapterAudioStreams


on(event, handler): Unsubscribe

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:861

"state"

(s) => void

Unsubscribe

VoiceSession.on

on(event, handler): Unsubscribe

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:862

"transcript"

(t) => void

Unsubscribe

VoiceSession.on

on(event, handler): Unsubscribe

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:863

"turn_mode"

(event) => void

Unsubscribe

VoiceSession.on

on(event, handler): Unsubscribe

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:871

Subscribes to retained fixed-greeting lifecycle changes. The handler runs after each change, not immediately on subscription; read RealtimeSession.greetingState first for the current retained value. Disconnects and stale connection generations cannot publish late changes into a replacement generation.

"greeting_state"

(state) => void

Unsubscribe

VoiceSession.on


requestGeneratedOpening(instructions): Promise<boolean>

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:401

Requests generated wording once per session memory, including provider recreation. Returns true only after adapter acceptance, never as proof of audible delivery. Returns false when no opening was requested: unsupported, disconnected, already attempted, or a fixed greeting is configured. A rejection still consumes the attempt because the provider may already have received it. No intended text becomes a transcript or Engine history entry. Configured generatedOpening uses this same claim. The claim is the one direct write into memory: it is a compare-and-set whose answer gates the request, so it cannot be an event. opening.claimed is published only after the claim is won.

string

Promise<boolean>


skipGreeting(): void

Defined in: packages/realtime/src/lib/realtime-session/realtime-session.ts:660

Synchronously and idempotently skip the configured fixed greeting without disconnecting voice or changing turn mode. The coordinator proof wins before local work is aborted, so stale async continuations cannot replay or replace the retained skipped state.

void