# `SuperPi.AI.Provider`
[🔗](https://github.com/oleksandr/super-pi-beam/blob/v0.1.0/lib/super_pi/ai/provider.ex#L1)

Behaviour for a model provider.

A provider owns one model API. `SuperPi.AI.Providers` selects the provider for a model name.
To serve a model that Super-Pi does not support, write a module that implements this
behaviour and register it in the application environment:

    config :super_pi, :providers, [MyApp.MyProvider, SuperPi.AI.Providers.Gemini]

Providers earlier in the list win. `generate/2` receives the request payload (`:model`,
`:messages`, `:tools`, and so on) and an `:on_delta` callback. It returns `{:ok, message}`
or `{:error, reason}`. The message has the shape `%{"role" => "assistant", "content" => [...],
"usage" => %{...}}`. Call `on_delta` with the events that `SuperPi.AI.StreamNormalizer` emits.

# `on_delta`

```elixir
@type on_delta() :: (term() -&gt; any())
```

Streaming callback. Receives `StreamNormalizer` events.

# `configured?`

```elixir
@callback configured?() :: boolean()
```

Returns true when the provider has the credentials and settings that it needs.

# `generate`

```elixir
@callback generate(payload :: map(), opts :: [{:on_delta, on_delta()}]) ::
  {:ok, map()} | {:error, term()}
```

Runs a generation request.

# `handles?`

```elixir
@callback handles?(model :: String.t()) :: boolean()
```

Returns true when this provider serves `model`.

# `id`

```elixir
@callback id() :: String.t()
```

Stable provider identifier, for example `"gemini"`.

# `models`

```elixir
@callback models() :: [%{required(String.t()) =&gt; String.t()}]
```

Models to list in catalogs. Each entry has `"id"` and `"label"`.

# `normalize_model`
*optional* 

```elixir
@callback normalize_model(model :: String.t()) :: String.t()
```

Maps a requested name (for example a harness alias) to the model sent to the API.

# `format_error`

```elixir
@spec format_error(term()) :: String.t()
```

Readable text for a `generate/2` error reason. Strings pass through unchanged, so text
formatted once is not escaped again.

---

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