# `Nous.Messages.Gemini`
[🔗](https://github.com/nyo16/nous/blob/v0.17.1/lib/nous/messages/gemini.ex#L1)

Gemini format message conversion.

Handles conversion between internal Message structs and Google Gemini API format.

# `build_request_params`

```elixir
@spec build_request_params(Nous.Model.t(), [Nous.Message.t()], map()) :: map()
```

Build the `generateContent` request params shared by the Gemini and
Vertex AI providers (both speak the same wire format).

Expects already-merged settings (`model.default_settings` merged with the
per-request settings). Handles system-instruction extraction, the
`generationConfig` mapping, tools, safety settings, tool config, and cached
content. Vendor `:extra_body` merging stays provider-side, where the
`Nous.Provider` macro enforces the blocked-key policy.

# `build_tools`

```elixir
@spec build_tools([map()], [atom() | tuple() | map()] | nil) :: [map()] | nil
```

Build Vertex's `tools` array from function declarations and native tools.

- `function_declarations` — list of Gemini-shaped function declarations
  (already converted via `Nous.ToolSchema.to_gemini/1`). May be empty.
- `native_tools` — list of native Vertex tools, each one of:
    * `:google_search`
    * `:url_context`
    * `:code_execution`
    * `{atom_or_string, %{config}}` — for tools that take configuration
    * a raw map — passed through (e.g. `%{"googleSearch" => %{}}`)

Returns `nil` when both lists are empty so callers can `maybe_put`.

# `from_messages`

```elixir
@spec from_messages([map()]) :: [Nous.Message.t()]
```

Convert Gemini format messages to internal Message structs.

# `from_response`

```elixir
@spec from_response(map()) :: Nous.Message.t()
```

Parse Gemini response into a Message.

## Examples

    iex> response = %{"candidates" => [%{"content" => %{"parts" => [%{"text" => "Hello"}]}}]}
    iex> message = Messages.Gemini.from_response(response)
    iex> {message.role, message.content}
    {:assistant, "Hello"}

# `json_config_for_settings`

```elixir
@spec json_config_for_settings(map() | keyword()) :: map()
```

Derive Gemini's `responseMimeType`/`responseSchema` pair from generic settings.

Honors three settings keys, in priority order:

- `:json_schema` (map) — forces JSON mime type and sets the schema.
- `:response_format` (map) — accepts `%{type: :json_schema, schema: schema}` or
  `%{type: :json_object}` for cross-provider consistency.
- `:json_response` (boolean) — forces JSON mime type without a schema.

Returns a map with `"responseMimeType"` and (optionally) `"responseSchema"`,
or `%{}` when none apply.

# `normalize_safety_settings`

```elixir
@spec normalize_safety_settings([map()] | nil) :: [map()] | nil
```

Normalize a list of safety settings into Vertex's `safetySettings` shape.

Accepts atom-keyed (`%{category: ..., threshold: ...}`) or string-keyed
(`%{"category" => ..., "threshold" => ...}`) entries. Passes unknown keys
through so newer Vertex fields (e.g. `"method"`) work without a library
bump. Returns `nil` for nil input.

# `normalize_thinking_config`

```elixir
@spec normalize_thinking_config(map() | nil) :: map() | nil
```

Normalize a Nous-shaped `thinking_config` into Gemini's `thinkingConfig`.

Accepts either the Elixir shape (`%{thinking_budget: 1024, include_thoughts:
true}`) or the native Vertex shape (`%{"thinkingBudget" => 1024,
"includeThoughts" => true}`). Returns `nil` when the input is nil.

Unrecognized keys are passed through unchanged so newer Vertex fields work
without a library bump.

# `normalize_tool_choice`

```elixir
@spec normalize_tool_choice(atom() | tuple() | map() | nil) :: map() | nil
```

Normalize a `:tool_choice` setting into Vertex's `toolConfig` shape.

Accepts:

  * `:auto` → mode `AUTO`
  * `:any` / `:required` → mode `ANY` (model must call a function)
  * `:none` → mode `NONE`
  * `{:any, ["name_a", ...]}` → mode `ANY` with `allowedFunctionNames`
  * a raw map (passed through as-is)
  * `nil` (returns nil)

# `parse_usage`

```elixir
@spec parse_usage(map() | nil) :: Nous.Usage.t()
```

Parse a Gemini-format `usageMetadata` map into a `%Nous.Usage{}` struct.

Used by both the non-streaming response parser and the streaming normalizer.

# `to_format`

```elixir
@spec to_format([Nous.Message.t()]) :: {String.t() | nil, [map()]}
```

Convert messages to Gemini format.

Returns `{system_prompt, contents}` where system prompt is extracted
and messages are converted to Gemini contents format.

## Examples

    iex> messages = [Message.system("Be helpful"), Message.user("Hello")]
    iex> Messages.Gemini.to_format(messages)
    {"Be helpful", [%{"role" => "user", "parts" => [%{"text" => "Hello"}]}]}

---

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