The upstream key, or a keyless sentinel (none / self-hosted / local / n/a)
for unauthenticated self-hosted endpoints. The inherited SDK client is never used for the
socket (the raw-WS adapter is), so the sentinel is harmless there too.
ProtectedapiOnly sub-classes can access the API key
Read-only accessor for the underlying OpenAI SDK client.
ProtectedProfileThe HuggingFace knobs + GA feature gates the shared protocol implementation runs with.
The compat layer's TTS stage has no OpenAI-style selectable voice catalog, so the dev voice
picker gets none — overriding away the OpenAI voice list this class would otherwise inherit.
(A voice Config value still passes through to audio.output.voice for stacks that honor it.)
HuggingFace supports client-direct via MJAPI's realtime proxy.
Whether this driver's sessions carry a video track in addition to audio — i.e. the model accepts video input (it can "see" the user's camera) and/or emits video output (a talking-head avatar / generated video), in sync with audio.
Defaults to false (audio-only — today's realtime models). Video-capable drivers (a native
multimodal realtime model, or an avatar provider) override this to true. The session's media
plane is media-tagged (IRealtimeSession.SendInput takes a RealtimeMediaKind;
IRealtimeSession.OnVideoOutput delivers video-out), so a video session reuses the entire
realtime contract — only the media frames gain a video kind. Resolution prefers a video-capable
model when an agent requests video, and degrades to audio-only otherwise.
true if sessions can carry video; false (audio-only) otherwise.
Mints the client-direct config: a one-time proxy ticket pointing at the internal endpoint, and
the private-pact SessionConfig the same-keyed 'huggingface' client driver consumes:
{ session, sampleRate }, where session is the OpenAI-Realtime session.update payload
(server-authored prompt/tools/voice) and sampleRate drives the client's PCM audio plane.
EphemeralToken is the browser-facing wss://<mjapi-public>/realtime-proxy?ticket=… URL.
Fully overrides the base's SDK client-secret mint — a self-hosted endpoint has no
/realtime/client_secrets API, and the proxy keeps MJAPI the single ingress.
ProtectedcreateCreates the realtime connection for a model. Overridable seam for testing.
Production returns a real OpenAIRealtimeWebSocket. Unit tests override this to return a
fake IOpenAIRealtimeConnection that emits OpenAI-shaped events and captures sends.
The provider realtime model id (e.g. gpt-realtime-2.1).
A connection implementing IOpenAIRealtimeConnection.
ProtectedcreateBuilds the raw-WS connection for the upstream endpoint. Overridable seam for testing — unit tests return an in-memory fake implementing IOpenAIRealtimeConnection, so no network.
NOTE: the platform-global WebSocket cannot send an Authorization header; upstream auth is
enforced by the endpoint itself or injected server-side by the MJAPI realtime proxy
(resolveUpstreamAuthHeader feeds the proxy ticket, not this socket).
The resolved ws(s)://…/v1/realtime endpoint URL.
The connection the shared session runs over.
ProtectedcreateCreates the session wrapper for a freshly-opened connection. Overridable seam so subclasses can return their own session subclass while StartSession stays shared.
The open provider connection.
The session bound to this driver's Profile.
ProtectedmintMints the ephemeral client secret via the provider's Realtime client-secrets API (resolved from the SDK client's base URL, so OpenAI-compatible subclasses target their own endpoint). Overridable seam for testing — unit tests return a fake response so no network call is made.
The client-secret create request (carries the realtime session config).
The client-secret create response (token value + expiry + echoed session).
ProtectedresolveResolves the browser-facing proxy ORIGIN as a ws(s)://host[:port] string. Precedence:
params.Config.proxyBaseUrl override → MJAPI_PUBLIC_URL → GRAPHQL_BASE_URL + GRAPHQL_PORT
(the same env vars MJAPI derives its public URL from). Any path on the source URL is dropped — only
the origin is used, and REALTIME_PROXY_PATH is appended by the caller.
ProtectedresolveBuilds the upstream Authorization header from the API key, or undefined when the endpoint is
unauthenticated. Because the realtime resolver requires a resolvable API key for a model to be
selectable, a keyless self-hosted deployment sets a sentinel value (none / self-hosted / local
/ n/a) for AI_VENDOR_API_KEY__HuggingFaceRealtime — treated here as "no auth" so no bogus header
is ever sent upstream (consumed by the MJAPI realtime proxy; the raw browser/Node socket cannot
carry headers at all).
ProtectedresolveResolves the internal upstream endpoint: params.Config.endpoint override → HUGGINGFACE_REALTIME_URL
env var → the local default. Self-hosted, so this is deployment config, not a hardcoded provider URL.
Opens a server-bridged session over the raw-WS adapter and — unlike the base — resolves only
after the initial config has been APPLIED (the endpoint's session.created handshake), so the
model is configured before any audio streams. Transport death during startup rejects.
StaticBuildBuilds the OpenAI-Realtime session object from the Core params:
instructions: the system prompt, with InitialContext folded in under a "Prior context"
heading (the compat protocol has no guaranteed history-seeding channel).tools: the Core tool set mapped to the OpenAI { type: 'function', … } schema.audio.output.voice: from params.Config.voice, when supplied.audio.input.transcription.model: from params.Config.inputTranscriptionModel, when supplied
(the pipeline's STT stage transcribes the user natively; this only names a specific model if the
compat layer supports selecting one).StaticComposeFolds optional prior context into the system prompt (no guaranteed history channel).
OptionalinitialContext: stringStaticHttpConverts an http(s) URL (or origin) into a ws(s)://host[:port] origin, dropping any path.
StaticMapMaps a Core tool definition to an OpenAI-Realtime function tool schema.
Protected StaticreadReads a process env var (indirected so tests can stub it and non-Node runtimes don't throw).
StaticResolveResolves the PCM sample rate: params.Config.sampleRate override, else the HF-native 16 kHz default.
StaticToolCanonical, order-insensitive fingerprint of a tool set (same scheme as the AssemblyAI / Gemini / ElevenLabs realtime drivers) — used to no-op identical live re-registrations.
Real-time, full-duplex driver for a self-hosted HuggingFace speech-to-speech server running in OpenAI-Realtime-compatible mode. Registers as
HuggingFaceRealtimeand is resolved forMJ: AI ModelstypedRealtime(API-key env alias:AI_VENDOR_API_KEY__HuggingFaceRealtime— optional; many self-hosted endpoints are unauthenticated).Topologies:
StartSessionresolves only after the session config has been applied (the endpoint'ssession.created→session.updatehandshake) so the runner never streams audio against an unconfigured model (obligation #7).wss://<mjapi-public>/realtime-proxy?ticket=…URL. The browser opens its socket to MJAPI's proxy, which tunnels transparently to the internal endpoint (injecting any auth server-side). The internal endpoint never reaches the browser and needs no browser-facing ingress.No managed server object and no usage billing: the entire session config (prompt, tools, voice) is supplied per session; there is no token-usage meter, so
OnUsagefires only if the compat endpoint happens to report aresponse.doneusage block.