# `Jido.AI.Actions.Helpers`
[🔗](https://github.com/agentjido/jido_ai/blob/v2.4.0/lib/jido_ai/actions/helpers.ex#L1)

Shared helper functions for Jido.AI skill actions.

This module provides common functionality used across multiple action modules
to reduce code duplication and ensure consistent behavior.

## Functions

* `resolve_model/2` - Resolve model alias to spec
* `build_opts/2` - Build options for LLM requests
* `extract_text/1` - Extract text from LLM response
* `extract_usage/1` - Extract usage information from response
* `validate_and_sanitize_input/2` - Validate input with security checks

## Examples

    use Jido.AI.Actions.Helpers

    # In an action
    def run(params, _context) do
      with {:ok, model} <- resolve_model(params[:model], :fast),
           {:ok, messages} <- build_messages(params),
           opts <- build_opts(params),
           {:ok, response} <- ReqLLM.Generation.generate_text(model, messages, opts) do
        {:ok, format_result(response)}
      end
    end

# `build_opts`

Builds ReqLLM options from action parameters.

## Parameters

* `params` - Map containing :max_tokens, :temperature, :timeout keys

## Returns

Keyword list of options for ReqLLM

## Examples

    iex> build_opts(%{max_tokens: 1000, temperature: 0.5})
    [max_tokens: 1000, temperature: 0.5]

    iex> build_opts(%{max_tokens: 1000, temperature: 0.5, timeout: 5000})
    [max_tokens: 1000, temperature: 0.5, receive_timeout: 5000]

# `emit_llm_complete`

Emits canonical completion telemetry for direct LLM actions.

Returns the canonical usage map so action results can reuse the same values.

# `emit_llm_error`

Emits canonical error telemetry for direct LLM actions.

# `extract_text`

Extracts text content from an LLM response.

Delegates to `Jido.AI.Turn.extract_text/1` which handles
multiple response shapes consistently.

## Parameters

* `response` - LLM response map

## Returns

Extracted text string

## Examples

    iex> extract_text(%{message: %{content: "Hello"}})
    "Hello"

    iex> extract_text(%{message: %{content: [%{type: :text, text: "Hi"}]}})
    "Hi"

# `extract_usage`

Extracts usage information from an LLM response.

## Parameters

* `response` - LLM response map

## Returns

Map with :input_tokens, :output_tokens, :total_tokens keys

## Examples

    iex> extract_text(%{usage: %{input_tokens: 10, output_tokens: 20}})
    %{input_tokens: 10, output_tokens: 20, total_tokens: 30}

# `format_result`

Formats a result with error sanitization.

If the result is {:ok, _}, returns it as-is.
If the result is {:error, _}, sanitizes the error message.

## Parameters

* `result` - The result tuple to format

## Returns

Formatted result tuple

## Examples

    iex> format_result({:ok, %{text: "Hello"}})
    {:ok, %{text: "Hello"}}

    iex> format_result({:error, %RuntimeError{message: "Internal"}})
    {:error, "An error occurred"}

# `resolve_model`

Resolves a model parameter to a model spec.

## Parameters

* `model` - Model alias or direct ReqLLM model input
* `default` - Default model alias to use if model is nil

## Returns

* `{:ok, model_input}` - Successfully resolved model
* `{:error, :invalid_model_format}` - Invalid model format

## Examples

    iex> resolve_model(nil, :fast)
    {:ok, "anthropic:claude-haiku-4-5"}

    iex> resolve_model(:capable, :fast)
    {:ok, "anthropic:claude-sonnet-4-20250514"}

    iex> resolve_model("openai:gpt-4", :fast)
    {:ok, "openai:gpt-4"}

# `sanitize_error`

Sanitizes an error for user-facing display.

Uses `Jido.AI.Error.Sanitize.sanitize_error_message/1` to convert
detailed errors into generic user-safe messages.

## Parameters

* `error` - The error term to sanitize

## Returns

Sanitized error message string

## Examples

    iex> sanitize_error(%RuntimeError{message: "Internal error"})
    "An error occurred"

    iex> sanitize_error(:timeout)
    "Request timed out"

# `telemetry_error_type`

Classifies action-layer LLM errors into canonical telemetry error types.

# `telemetry_metadata`

Builds canonical AI telemetry metadata for direct LLM actions.

# `token_measurements`

```elixir
@spec token_measurements(term()) :: %{
  input_tokens: non_neg_integer(),
  output_tokens: non_neg_integer(),
  total_tokens: non_neg_integer()
}
```

Builds canonical token measurements for AI telemetry events.

# `validate_and_sanitize_input`

Validates and sanitizes input parameters with security checks.

## Parameters

* `params` - Map of input parameters
* `opts` - Validation options:
  * `:required_prompt` - Whether prompt is required (default: true)
  * `:required_system_prompt` - Whether system_prompt must be validated if present
  * `:max_prompt_length` - Max length for prompt (default: Validation.max_input_length())
  * `:max_system_prompt_length` - Max length for system_prompt (default: Validation.max_prompt_length())

## Returns

* `{:ok, params}` - Validation passed
* `{:error, reason}` - Validation failed

## Examples

    iex> validate_and_sanitize_input(%{prompt: "Hello"})
    {:ok, %{prompt: "Hello"}}

    iex> validate_and_sanitize_input(%{prompt: ""})
    {:error, :prompt_required}

---

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