# `ALLM.Usage`
[🔗](https://github.com/cykod/ALLM/blob/v0.3.0/lib/allm/usage.ex#L1)

Token and cost usage for a single response. See spec §5.9a.

Layer A — pure serializable data. Every numeric field is optional and
`nil`-able because not every provider returns every counter. Costs are
populated either by an adapter that knows its own pricing or (in Phase 9)
by an optional `llm_db` integration.

# `cost`

```elixir
@type cost() :: float()
```

# `t`

```elixir
@type t() :: %ALLM.Usage{
  cached_input_tokens: non_neg_integer() | nil,
  extra: map(),
  input_cost: cost() | nil,
  input_tokens: non_neg_integer() | nil,
  output_cost: cost() | nil,
  output_tokens: non_neg_integer() | nil,
  reasoning_tokens: non_neg_integer() | nil,
  tool_usage: map(),
  total_cost: cost() | nil,
  total_tokens: non_neg_integer() | nil
}
```

# `new`

```elixir
@spec new(keyword()) :: t()
```

Build a `%Usage{}` from keyword opts.

Every field is optional. Unknown keys raise `ArgumentError` via `struct!/2`.

## Examples

    iex> u = ALLM.Usage.new(input_tokens: 10, output_tokens: 20)
    iex> u.input_tokens
    10
    iex> u.tool_usage
    %{}

# `total_tokens`

```elixir
@spec total_tokens(t()) :: non_neg_integer() | nil
```

Return the `:total_tokens` field when set, otherwise the sum of
`:input_tokens + :output_tokens` when both are integers, otherwise `nil`.

## Examples

    iex> ALLM.Usage.total_tokens(ALLM.Usage.new(total_tokens: 42))
    42

    iex> ALLM.Usage.total_tokens(ALLM.Usage.new(input_tokens: 10, output_tokens: 20))
    30

    iex> ALLM.Usage.total_tokens(ALLM.Usage.new([]))
    nil

---

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