bodhi-realtime-agent / LLMTransport
Interface: LLMTransport
Defined in: src/types/transport.ts:597
Properties
audioFormat
readonlyaudioFormat:AudioFormatSpec
Defined in: src/types/transport.ts:634
capabilities
readonlycapabilities:TransportCapabilities
Defined in: src/types/transport.ts:599
Static capabilities — read before connecting, used for orchestrator branching.
currentDialGen?
readonlyoptionalcurrentDialGen?:number
Defined in: src/types/transport.ts:624
Dial counter: advances per dial and when the current dial fails.
currentTransportGeneration?
readonlyoptionalcurrentTransportGeneration?:number
Defined in: src/types/transport.ts:626
Post-setup generation counter (advances only on a completed setup).
isConnected
readonlyisConnected:boolean
Defined in: src/types/transport.ts:613
onAudioOutput?
optionalonAudioOutput?: (base64Data) =>void
Defined in: src/types/transport.ts:774
Parameters
base64Data
string
Returns
void
onCacheBust?
optionalonCacheBust?: (reason) =>void
Defined in: src/types/transport.ts:897
Fires immediately before the framework emits a session.update that changes instructions or tools — i.e. before a guaranteed full prompt-cache bust on the next response. Pure telemetry.
Parameters
reason
"instructions_changed" | "tools_changed"
Returns
void
onClose?
optionalonClose?: (code?,reason?) =>void
Defined in: src/types/transport.ts:798
Parameters
code?
number
reason?
string
Returns
void
onConnectionLifecycle?
optionalonConnectionLifecycle?: (event) =>void
Defined in: src/types/transport.ts:872
Connection-lifecycle facts (attempt / setup / close), correlated by connectAttemptId. An event's failure (and an attempt-closereason for a provider failure) may hold provider-supplied text: see ConnectFailure before logging it.
Parameters
event
Returns
void
onCredentialExpiry?
optionalonCredentialExpiry?: () =>void
Defined in: src/types/transport.ts:856
The credential of the current connection reached its expiry (GeminiLiveTransport with a credentialProvider). A consumer that can reconnect now should start that reconnect synchronously, as for a GoAway: right after this returns the transport closes the connection, unless a disconnect() already detached it, and reports the close through onClose and a generation-close lifecycle event.
Returns
void
onError?
optionalonError?: (error) =>void
Defined in: src/types/transport.ts:797
Parameters
error
Returns
void
onFirstAudioChunk?
optionalonFirstAudioChunk?: () =>void
Defined in: src/types/transport.ts:820
Fires once per model response, on the FIRST audio chunk emitted to the client. Distinct from onModelTurnStart (which fires as a response begins, including tool-only turns) — this marks the moment audio actually begins, the anchor for TTS-first-audio / stop-to-first-audio latency. Transports reset their per-response "audio started" flag when a new response begins.
Returns
void
onGenerationEnd?
optionalonGenerationEnd?: (generationId,reason) =>void
Defined in: src/types/transport.ts:813
That generation closed, and why. Fires exactly once per start.
Parameters
generationId
string
reason
GenerationEndReason
Returns
void
onGenerationStart?
optionalonGenerationStart?: (generationId) =>void
Defined in: src/types/transport.ts:811
A model generation opened. Paired with exactly one onGenerationEnd. A generation is one answer: it outlives the provider's turn boundary, because a tool call that finishes the answer can arrive after it.
Parameters
generationId
string
Returns
void
onGoAway?
optionalonGoAway?: (timeLeft) =>void
Defined in: src/types/transport.ts:849
Parameters
timeLeft
string
Returns
void
onGroundingMetadata?
optionalonGroundingMetadata?: (metadata) =>void
Defined in: src/types/transport.ts:858
Parameters
metadata
Record<string, unknown>
Returns
void
onInputTranscription?
optionalonInputTranscription?: (text) =>void
Defined in: src/types/transport.ts:794
User-speech transcription from the transport's own recognizer.
Parameters
text
string
An incremental delta, not the whole utterance restated. Gemini Live streams many small deltas per utterance (often mid-word); OpenAI and Qwen fire once per utterance from conversation.item.input_audio_transcription.completed, which is the degenerate one-delta case. Consumers must therefore accumulate across calls and reset at each utterance boundary — treating a call as the complete transcript collapses the utterance to its last fragment.
Returns
void
onInterrupted?
optionalonInterrupted?: (serverTurnId?) =>void
Defined in: src/types/transport.ts:784
Parameters
serverTurnId?
number
Monotonic id of the server turn being interrupted (see onTurnComplete). undefined for transports without server turns.
Returns
void
onModelTurnStart?
optionalonModelTurnStart?: (generationId?) =>void
Defined in: src/types/transport.ts:807
Fires when the model begins a response (audio, text, tool call). Used by VoiceSession to trigger STT provider commit.
Parameters
generationId?
string
The generation that opened, on transports that model generations (GeminiLiveTransport: once per generation, with the same id as onGenerationStart, so a tool call after turnComplete that finishes the same answer does not fire it again); undefined elsewhere.
Returns
void
onOutputTranscription?
optionalonOutputTranscription?: (text) =>void
Defined in: src/types/transport.ts:795
Parameters
text
string
Returns
void
onProviderEvidence?
optionalonProviderEvidence?: (ev) =>void
Defined in: src/types/transport.ts:903
Normalized provider-evidence delivery (speech-evidence design §1). Adapters of transports that declare capabilities.providerEvidenceKinds emit each normalized event here; the framework routes it into the session's evidence ledger. Never emit kinds you did not declare.
Parameters
ev
ProviderEvidenceEvent
Returns
void
onRealtimeLLMUsage?
optionalonRealtimeLLMUsage?: (usage) =>void
Defined in: src/types/transport.ts:861
Optional: fires when the provider reports token or duration usage for billing/observability.
Parameters
usage
Returns
void
onReasoningDone?
optionalonReasoningDone?: (info) =>void
Defined in: src/types/transport.ts:886
Fires when the model's reasoning step completes for the current response, before any audio/text answer is emitted. durationMs is the wall-clock time the reasoning step took; reasoningTokens is the count if the provider exposes it (otherwise undefined).
Parameters
info
durationMs
number
reasoningTokens?
number
Returns
void
onReasoningStart?
optionalonReasoningStart?: () =>void
Defined in: src/types/transport.ts:880
Fires when the model begins emitting its hidden reasoning trace for the current response. Useful for latency observability.
Returns
void
onReasoningSummary?
optionalonReasoningSummary?: (text) =>void
Defined in: src/types/transport.ts:891
Fires with a streamed chunk of the optional reasoning summary text (when the model was configured to emit one). Surface this to ops telemetry only — never to end users.
Parameters
text
string
Returns
void
onResumptionUpdate?
optionalonResumptionUpdate?: (handle,resumable) =>void
Defined in: src/types/transport.ts:857
Parameters
handle
string
resumable
boolean
Returns
void
onSessionReady?
optionalonSessionReady?: (sessionId) =>void
Defined in: src/types/transport.ts:796
Parameters
sessionId
string
Returns
void
onSpeechStarted?
optionalonSpeechStarted?: () =>void
Defined in: src/types/transport.ts:837
Fires when the transport detects user speech via VAD. Used for TTS-level barge-in when the LLM is idle but TTS is still playing. OpenAI: wired to input_audio_buffer.speech_started. Gemini: may require custom VAD signal — needs empirical testing.
Returns
void
onTextDone?
optionalonTextDone?: () =>void
Defined in: src/types/transport.ts:831
Fires when the model's text response is complete for this turn. Signals that all text for the current response has been delivered. Ordering contract: fires after all onTextOutput, before onTurnComplete.
Returns
void
onTextOutput?
optionalonTextOutput?: (text) =>void
Defined in: src/types/transport.ts:826
Fires when the model produces text output (text-mode responses). Only active when responseModality is 'text' (i.e., external TTS in use).
Parameters
text
string
Incremental text chunk (may be partial word/sentence)
Returns
void
onToolCall?
optionalonToolCall?: (calls) =>void
Defined in: src/types/transport.ts:775
Parameters
calls
Returns
void
onToolCallCancel?
optionalonToolCallCancel?: (ids) =>void
Defined in: src/types/transport.ts:776
Parameters
ids
string[]
Returns
void
onTurnComplete?
optionalonTurnComplete?: (serverTurnId?) =>void
Defined in: src/types/transport.ts:781
Parameters
serverTurnId?
number
Monotonic id of the server turn that completed, when the transport models server turns explicitly (Gemini external-TTS path). Consumers dedupe finalization by this id. undefined for transports that do not track server turns.
Returns
void
onUsageMetadata?
optionalonUsageMetadata?: (usage) =>void
Defined in: src/types/transport.ts:865
Optional: the provider's raw usage payload, once per server message that carries it (including messages that also carry audio, a tool call or goAway). Declared by GeminiLiveTransport only.
Parameters
usage
Returns
void
onUserSpeechStopped?
optionalonUserSpeechStopped?: () =>void
Defined in: src/types/transport.ts:846
Fires when the provider's server VAD detects end of user speech. OpenAI/Qwen: wired to input_audio_buffer.speech_stopped. Gemini Live has no equivalent wire event (callback never fires there — the framework falls back to client-VAD timing). The latency anchor derived from this is callback receipt time: biased late by the provider's silence window + network hop (a bounded lower-bound bias — see the observability design, investment-hai-metrics-observability.md §11).
Returns
void
Methods
abortIncumbent()?
optionalabortIncumbent():Promise<"closed"|"forced">
Defined in: src/types/transport.ts:622
Synchronously strand the incumbent connection — advance the dial generation so its callbacks, an in-flight reconnect() continuation and a later-resolving dial can no longer install or deliver anything, detach the session, and drop the resumption handle — then close it within a bounded time. Never rejects: 'closed' when the close completed, 'forced' on timeout or close error. Unlike disconnect(), never awaited unboundedly.
Returns
Promise<"closed" | "forced">
cancelResponse()?
optionalcancelResponse(opts?):Promise<void>
Defined in: src/types/transport.ts:669
Cancel the in-flight response — wire-only actuation. May be called from any framework barge-in path that has decided to interrupt. Idempotent.
MUST NOT invoke onInterrupted or any other framework callback — the caller is responsible for finalizeTurn(interrupted). The implementation only sends wire messages and updates the transport's own state.
MUST NOT reject. Transient send failures are caught and logged internally; the returned promise still resolves so fire-and-forget callers cannot trigger unhandled-rejection warnings.
When truncate.audioEndMs is supplied and the transport tracks an active assistant audio item, it also sends a per-provider truncate (OpenAI: conversation.item.truncate). truncate: 'generated' asks the transport to compute audioEndMs from its own per-response generated-audio counter (e.g. OpenAI's audioOutputMs); transports without such a counter ignore the sentinel. Omitting truncate only skips truncation — cancelResponse still stops generation if a response is in flight.
When waitForDone is true, the returned promise resolves only after the trailing response.done(status:'cancelled') arrives from the provider (or a 2000 ms timeout, whichever comes first). Use this before sending a new response.create so cancel and create cannot race. Default false.
Parameters
opts?
CancelResponseOptions
Returns
Promise<void>
clearAudio()
clearAudio():
void
Defined in: src/types/transport.ts:638
Returns
void
clearInputAudio()?
optionalclearInputAudio():void
Defined in: src/types/transport.ts:676
Clear the provider's pending input-audio buffer (OpenAI Realtime: input_audio_buffer.clear). Optional — Gemini and other transports without a server-side append-then-commit input buffer omit this. Called by VoiceSession at grace-window arming to discard any pre-arming echo residue; safe to call when the buffer is empty.
Returns
void
clearResumption()?
optionalclearResumption():void
Defined in: src/types/transport.ts:630
Drop every copy of the session resumption handle the transport holds, so the next dial opens a fresh server session instead of resuming the current one. Does not touch the connection itself.
Returns
void
commitAudio()
commitAudio():
void
Defined in: src/types/transport.ts:637
Returns
void
connect()
connect(
config?):Promise<void>
Defined in: src/types/transport.ts:602
Parameters
config?
Returns
Promise<void>
disconnect()
disconnect():
Promise<void>
Defined in: src/types/transport.ts:603
Returns
Promise<void>
elicitResponse()?
optionalelicitResponse():void
Defined in: src/types/transport.ts:754
Best-effort re-elicit of a model response from existing/restored context, without injecting new content. Used after a watchdog-driven reconnect to recover a turn the model silently dropped. Optional — transports that auto-generate (or cannot elicit without content) may omit it; callers fall back to triggerGeneration().
Implement this only when the provider accepts a genuinely content-less request. No in-tree transport does: Gemini rejects one server-side (1007, see the note in GeminiLiveTransport), and OpenAI/Qwen rely on the triggerGeneration() fallback. A rejection here is especially costly because it surfaces as an async socket close, not a throw, so the watchdog reads it as a transport failure and retries into the reconnect budget.
Returns
void
getActiveServerTurnId()?
optionalgetActiveServerTurnId():number|undefined
Defined in: src/types/transport.ts:771
The transport's currently-active server-turn id, or undefined when no server turn is active (idle/closed) or the transport does not model server turns. Read synchronously from a model-output callback to bind the framework Turn to the server turn at birth. Active-only by contract: it must NOT return a stale id between turns.
Returns
number | undefined
getDiagnostics()?
optionalgetDiagnostics():TransportDiagnostics
Defined in: src/types/transport.ts:875
Snapshot of the upstream send counters and the current transport generation. Absent on transports that do not count sends.
Returns
quiesce()?
optionalquiesce():Promise<void>
Defined in: src/types/transport.ts:687
Pause the transport without disconnecting:
- Cancel any in-flight model response (provider chooses how).
- Suppress onAudioOutput deltas until unquiesce() is called.
- Leave the WebSocket open and conversation state intact.
Idempotent. Used by VoiceSession to transition into transcription mode without tearing the transport down. When omitted, VoiceSession falls back to its framework-layer audio-output guard.
Returns
Promise<void>
reconnect()
reconnect(
state?):Promise<void>
Defined in: src/types/transport.ts:604
Parameters
state?
Returns
Promise<void>
replayHistory()?
optionalreplayHistory(items):void
Defined in: src/types/transport.ts:612
Replay prior turns into the live upstream session as quiet context (no response requested). Called AFTER connect() and BEFORE the next send, for a session that has no server-side conversation: the host's initialHistory on the first connection that sets up (resume), and the whole conversation on a host-recovery replacement connection. Not idempotent: the caller sends a given conversation to a given connection once. Optional — a transport that cannot prefill omits it (VoiceSession calls it as transport.replayHistory?.(...)). Distinct from reconnect recovery, which transports drive internally from ReconnectState.
Parameters
items
readonly ReplayItem[]
Returns
void
replayUserTurn()?
optionalreplayUserTurn(turn):boolean
Defined in: src/types/transport.ts:763
Re-send a retained user utterance as a complete user turn, eliciting a response. Used by the response watchdog when a stalled turn left pending user input the provider never answered — first in-place on the existing connection, then once more after a reconnect if the model stays silent. Returns true if the transport dispatched it; false/absent → caller falls back. Optional. Gemini sends clientContent inline audio with an explicit turnComplete (no server-VAD dependence; Phase 0 validated).
Parameters
turn
RetainedUserTurn
Returns
boolean
sendAudio()
sendAudio(
base64Data):void
Defined in: src/types/transport.ts:633
Parameters
base64Data
string
Returns
void
sendContent()
sendContent(
turns,turnComplete?):void
Defined in: src/types/transport.ts:708
Parameters
turns
turnComplete?
boolean
Returns
void
sendFile()
sendFile(
base64Data,mimeType):void
Defined in: src/types/transport.ts:718
Parameters
base64Data
string
mimeType
string
Returns
void
sendInlineFile()?
optionalsendInlineFile(base64Data,mimeType):void
Defined in: src/types/transport.ts:723
Send a file of any MIME type inline in the conversation content, without completing the turn (documents that sendFile's realtime media path cannot carry). Optional: without it, such files go to sendFile.
Parameters
base64Data
string
mimeType
string
Returns
void
sendLiveText()?
optionalsendLiveText(turns):boolean
Defined in: src/types/transport.ts:715
Send live, generation-triggering text through the provider's realtime input. Returns true when the send was dispatched or accepted into a send buffer (flushed best effort) and false when it was not (no text, not connected, or a send that failed). Never throws. Optional: a transport without it takes live text through sendContent(turns, true).
Parameters
turns
Returns
boolean
sendToolResult()
sendToolResult(
result):void
Defined in: src/types/transport.ts:726
Parameters
result
Returns
void
transferSession()
transferSession(
config,state?):Promise<void>
Defined in: src/types/transport.ts:705
Parameters
config
state?
Returns
Promise<void>
triggerGeneration()
triggerGeneration(
instructions?,overrides?):void
Defined in: src/types/transport.ts:737
Trigger a model response.
Parameters
instructions?
string
Optional one-off instruction (passed as response.create.response.instructions on OpenAI — does not mutate the session prefix, so it is cache-safe for subsequent turns).
overrides?
Optional per-response overrides. reasoning.effort bumps the dial for this Response only (resets to session default on the next turn). Only honored by transports advertising capabilities.reasoningEffort.
reasoning?
{ effort: ReasoningEffort; }
reasoning.effort
Returns
void
unquiesce()?
optionalunquiesce():Promise<void>
Defined in: src/types/transport.ts:691
Resume normal operation after quiesce(). After this resolves, onAudioOutput fires again on the next response. Idempotent.
Returns
Promise<void>
updateSession()
updateSession(
config):void|Promise<void>
Defined in: src/types/transport.ts:702
Apply a session update. Pre-connect: state-only mutation; coalesces with prior pre-connect calls and resolves immediately. The merged config is sent in the single session.update issued at connect time. Post-connect: serialized via the transport's internal FIFO queue; each call produces one wire session.update and awaits its ack. A custom transport may instead apply the update synchronously and return void.
Parameters
config
Returns
void | Promise<void>