# `Gemini.Client.WebSocket`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.13.0/lib/gemini/client/websocket.ex#L1)

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

# `auth_strategy`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.13.0/lib/gemini/client/websocket.ex#L64)

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

# `connection_error`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.13.0/lib/gemini/client/websocket.ex#L86)

```elixir
@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`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.13.0/lib/gemini/client/websocket.ex#L65)

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

# `retry_config`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.13.0/lib/gemini/client/websocket.ex#L80)

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

# `t`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.13.0/lib/gemini/client/websocket.ex#L67)

```elixir
@type t() :: %Gemini.Client.WebSocket{
  api_key: String.t() | nil,
  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
}
```

# `close`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.13.0/lib/gemini/client/websocket.ex#L374)

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

Closes the WebSocket connection gracefully.

## Parameters

- `conn` - The WebSocket connection struct

## Returns

- `:ok` - Always returns :ok

# `connect`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.13.0/lib/gemini/client/websocket.ex#L189)

```elixir
@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` - Gemini API version for `:gemini` connections (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?`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.13.0/lib/gemini/client/websocket.ex#L402)

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

Checks if the connection is active.

# `receive`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.13.0/lib/gemini/client/websocket.ex#L291)

```elixir
@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`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.13.0/lib/gemini/client/websocket.ex#L350)

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

Receives all available messages without blocking.

Returns a list of messages that are immediately available.

# `retryable_error?`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.13.0/lib/gemini/client/websocket.ex#L420)

```elixir
@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`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.13.0/lib/gemini/client/websocket.ex#L259)

```elixir
@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`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.13.0/lib/gemini/client/websocket.ex#L396)

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

Returns the current connection status.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
