Interface RealtimeExtensionContextExperimental

The fal.realtime.open() extension API is experimental and may change in a minor release.

interface RealtimeExtensionContext {
    endpointId: string;
    signal: AbortSignal;
    addCleanup(cleanup: (() => void | Promise<void>)): void;
    close(): Promise<void>;
    connect<Input, Output>(endpointId: string, handler: RealtimeConnectionHandler<Output>): RealtimeConnection<Input>;
    data(raw: string): void;
    diagnostic(event: RealtimeDiagnostic): void;
    fail(message: string, observed?: Record<string, string | number>): Promise<void>;
    fetch(url: string, init?: Omit<RequestInit, "body"> & {
        body?: string;
    }): Promise<Response>;
    gatherIce(pc: RTCPeerConnection, options?: IceGatheringOptions): Promise<IceGatheringResult>;
    media(stream: MediaStream): void;
    run<Input, Output>(endpointId: string, options: RunOptions<Input>): Promise<Result<Output>>;
}

Properties

endpointId: string

The endpoint selected by fal.realtime.open().

signal: AbortSignal

Aborted when the caller cancels opening or closes the resulting session. Extensions should pass it to fetch-like work and check it between negotiation steps.

Methods

  • Experimental

    Register a resource release callback. Callbacks run once, in reverse order, when opening fails, the signal aborts, or the session closes.

    Parameters

    Returns void

  • Experimental

    End the managed session from inside the extension, for example when a provider reports that the remote session finished on its own.

    Returns Promise<void>

  • Experimental

    Publish one inbound message to onData. Raw; parsing belongs to the application.

    Parameters

    • raw: string

    Returns void

  • Experimental

    Report progress or failure to the caller, if it asked to hear about it.

    Safe to call unconditionally — the kernel drops the event when no onDiagnostic was supplied, so an extension never needs to check.

    Parameters

    Returns void

  • Experimental

    End the session because it FAILED, as opposed to being closed.

    close() alone cannot express this. A dead peer connection or an expired lease is not a clean teardown, but the kernel only sees a close request and reports "closed" — so a caller cannot distinguish "the user pressed disconnect" from "the transport died", which are the two cases a status UI most needs to tell apart.

    Emits a failure diagnostic, moves the state to "failed", then tears down.

    Parameters

    • message: string
    • Optionalobserved: Record<string, string | number>

    Returns Promise<void>

  • Experimental

    A credentialed request to fal infrastructure that is NOT an endpoint.

    run() covers fal endpoints and connect() covers the fal WebSocket, which leaves a real gap: a shared signalling bridge, a regional relay or a control plane addressed by body rather than path — say POST https://<service>.fal.run/session carrying the app id as a body parameter — is reachable through neither. Without this, the only way to reach one is for the APPLICATION to inject a credentialed fetch, which hands auth for one leg of the connection back to the caller and is exactly what this API exists to prevent.

    Applies the parent client's credentials, request middleware and proxy, so a proxied application stays proxied. Request bodies are JSON strings because that is the common body contract every supported proxy adapter preserves. Returns the raw Response: unlike run(), this makes no assumption that the other end speaks fal's result envelope.

    Parameters

    • url: string
    • Optionalinit: Omit<RequestInit, "body"> & {
          body?: string;
      }

    Returns Promise<Response>

  • Experimental

    Wait for ICE gathering to produce a usable candidate set.

    In the kernel because every extension doing browser WebRTC against a non-trickle signalling channel needs it, and both obvious strategies are wrong: waiting for complete pays a dead STUN server's full timeout, while a fixed short cap silently ships a host+srflx-only offer that can never form a relayed path and fails with no error at all.

    What works is sufficient-set, then a quiet period, under a hard bound. An extension that trickles its candidates has no use for it, which is precisely why it belongs here rather than inside whichever extension meets the problem first — otherwise the next one writes it again, slightly differently.

    Parameters

    Returns Promise<IceGatheringResult>

  • Experimental

    Call any fal endpoint with the same credentials, middleware, storage handling, and retry policy as the parent client. This is just for getting ICE servers from the app's own /ice endpoint in case the bridge is not available.

    Type Parameters

    • Input = unknown
    • Output = unknown

    Parameters

    Returns Promise<Result<Output>>