Gemini.Client.WebSocket (GeminiEx v0.9.1)

Copy Markdown View Source

WebSocket client for Gemini Live API using :gun.

This module provides low-level WebSocket connectivity with:

  • TLS/HTTP2 connection management
  • Automatic reconnection handling with configurable retry logic
  • Message framing and parsing
  • Auth strategy integration (Gemini API / Vertex AI)
  • Comprehensive telemetry integration

Usage

Typically used through Gemini.Live.Session rather than directly.

{:ok, conn} = WebSocket.connect(:gemini, model: "gemini-2.5-flash")
:ok = WebSocket.send(conn, %{setup: setup_config})
{:ok, message} = WebSocket.receive(conn)
:ok = WebSocket.close(conn)

Connection Options

  • :model - Required. Model name for the Live API
  • :project_id - Required for Vertex AI
  • :location - Vertex AI location (default: "us-central1")
  • :api_version - API version (default: "v1beta")
  • :timeout - Connection timeout in ms (default: 30000)
  • :retry_attempts - Number of retry attempts for transient failures (default: 3)
  • :retry_delay - Initial delay between retries in ms (default: 1000)
  • :retry_backoff - Backoff multiplier for retries (default: 2.0)

Connection State

The connection struct tracks:

  • Gun connection PID
  • Stream reference
  • Authentication strategy
  • Connection status

Endpoints

  • Gemini API: wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent?key=API_KEY
  • Vertex AI: wss://{location}-aiplatform.googleapis.com/ws/google.cloud.aiplatform.v1beta1.LlmBidiService/BidiGenerateContent?project=...&location=...

Telemetry Events

This module emits the following telemetry events:

  • [:gemini, :live, :websocket, :connect, :start] - Connection attempt started
  • [:gemini, :live, :websocket, :connect, :stop] - Connection established
  • [:gemini, :live, :websocket, :connect, :exception] - Connection failed
  • [:gemini, :live, :websocket, :send] - Message sent
  • [:gemini, :live, :websocket, :receive] - Message received
  • [:gemini, :live, :websocket, :close] - Connection closed
  • [:gemini, :live, :websocket, :retry] - Retry attempt

Summary

Functions

Closes the WebSocket connection gracefully.

Establishes a WebSocket connection to the Live API.

Checks if the connection is active.

Receives the next message from the WebSocket connection.

Receives all available messages without blocking.

Checks if an error is retryable.

Sends a message over the WebSocket connection.

Returns the current connection status.

Types

auth_strategy()

@type auth_strategy() :: :gemini | :vertex_ai

connection_error()

@type connection_error() ::
  :project_id_required_for_vertex_ai
  | :no_api_key
  | {:open_failed, term()}
  | {:connection_failed, term()}
  | {:upgrade_failed, integer(), list()}
  | {:upgrade_error, term()}
  | :upgrade_timeout
  | {:max_retries_exceeded, term()}

connection_status()

@type connection_status() :: :connecting | :connected | :closing | :closed

retry_config()

@type retry_config() :: %{
  attempts: non_neg_integer(),
  delay: non_neg_integer(),
  backoff: float()
}

t()

@type t() :: %Gemini.Client.WebSocket{
  api_version: String.t(),
  auth_strategy: auth_strategy() | nil,
  gun_pid: pid() | nil,
  location: String.t() | nil,
  model: String.t() | nil,
  project_id: String.t() | nil,
  retry_config: retry_config(),
  status: connection_status(),
  stream_ref: reference() | nil
}

Functions

close(conn)

@spec close(t()) :: :ok

Closes the WebSocket connection gracefully.

Parameters

  • conn - The WebSocket connection struct

Returns

  • :ok - Always returns :ok

connect(auth_strategy, opts \\ [])

@spec connect(
  auth_strategy(),
  keyword()
) :: {:ok, t()} | {:error, connection_error()}

Establishes a WebSocket connection to the Live API.

Parameters

  • auth_strategy - :gemini or :vertex_ai
  • opts - Connection options:
    • :model - Required. Model name
    • :project_id - Required for Vertex AI
    • :location - Vertex AI location (default: "us-central1")
    • :api_version - API version (default: "v1beta")
    • :timeout - Connection timeout in ms (default: 30000)
    • :retry_attempts - Number of retry attempts (default: 3)
    • :retry_delay - Initial retry delay in ms (default: 1000)
    • :retry_backoff - Backoff multiplier (default: 2.0)

Returns

  • {:ok, connection} - Successfully connected
  • {:error, reason} - Connection failed

Examples

{:ok, conn} = WebSocket.connect(:gemini, model: "gemini-2.5-flash-native-audio-preview-12-2025")

{:ok, conn} = WebSocket.connect(:vertex_ai,
  model: "gemini-2.5-flash-native-audio-preview-12-2025",
  project_id: "my-project",
  location: "us-central1"
)

# With custom retry configuration
{:ok, conn} = WebSocket.connect(:gemini,
  model: "gemini-2.5-flash",
  retry_attempts: 5,
  retry_delay: 2000,
  retry_backoff: 1.5
)

connected?(arg1)

@spec connected?(t()) :: boolean()

Checks if the connection is active.

receive(conn, timeout \\ 60000)

@spec receive(t(), timeout()) :: {:ok, map()} | {:error, term()}

Receives the next message from the WebSocket connection.

This is a blocking call that waits for the next message.

Parameters

  • conn - The connection struct
  • timeout - Timeout in milliseconds (default: 60000)

Returns

  • {:ok, message} - Received and parsed JSON message
  • {:error, :timeout} - No message received within timeout
  • {:error, :closed} - Connection closed
  • {:error, reason} - Other error

receive_all(conn)

@spec receive_all(t()) :: [map()]

Receives all available messages without blocking.

Returns a list of messages that are immediately available.

retryable_error?(arg1)

@spec retryable_error?(term()) :: boolean()

Checks if an error is retryable.

Returns true if the error is a transient failure that might succeed on retry.

Parameters

  • error - The error to check

Returns

  • true if the error is retryable
  • false otherwise

send(conn, message)

@spec send(t(), map()) :: :ok | {:error, term()}

Sends a message over the WebSocket connection.

The message should be a map that will be JSON-encoded.

Parameters

  • conn - The WebSocket connection struct
  • message - A map to be JSON-encoded and sent

Returns

  • :ok - Message sent successfully
  • {:error, reason} - Send failed

Example

:ok = WebSocket.send(conn, %{
  "clientContent" => %{
    "turns" => [%{"role" => "user", "parts" => [%{"text" => "Hello"}]}],
    "turnComplete" => true
  }
})

status(web_socket)

@spec status(t()) :: connection_status()

Returns the current connection status.