# `Cyclium.Batch`
[🔗](https://github.com/Cyclium/cyclium_ex/blob/main/lib/cyclium/batch.ex#L1)

Helpers for strategies that process data in grouped batches.

Strategies remain in full control of the episode loop — Batch provides
a lightweight struct for chunking data, tracking progress through groups,
and collecting results. No new step types are introduced; strategies
continue using `:tool_call` and `:synthesize` as normal.

## Usage

    # In strategy init — load items, group them, initialize batch
    items = load_all_items(product_id)
    batch = Cyclium.Batch.init(Cyclium.Batch.group_by(items, &base_item_id/1))

    # In next_step — drive the loop
    case Cyclium.Batch.current_group(state.batch) do
      nil -> :converge
      {group_key, items} -> {:synthesize, build_prompt(group_key, items)}
    end

    # In handle_result — advance to next group
    batch = Cyclium.Batch.advance(state.batch, parsed_result)
    {:ok, %{state | batch: batch}}

# `t`

```elixir
@type t() :: %Cyclium.Batch{
  current_index: non_neg_integer(),
  groups: [{term(), [term()]}],
  results: [term()]
}
```

# `advance`

```elixir
@spec advance(t(), term()) :: t()
```

Advance to the next group, storing the result from the current one.

# `chunk`

```elixir
@spec chunk([term()], pos_integer()) :: [{non_neg_integer(), [term()]}]
```

Chunk a flat list into groups of `size`.

Returns `{index, items}` tuples suitable for `init/1`.

# `current_group`

```elixir
@spec current_group(t()) :: {term(), [term()]} | nil
```

Get the current group to process.

Returns `{group_key, items}` or `nil` when all groups are done.

# `done?`

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

Check if all groups have been processed.

# `group_by`

```elixir
@spec group_by([term()], (term() -&gt; term())) :: [{term(), [term()]}]
```

Group items by a key function.

Returns `{group_key, items}` tuples suitable for `init/1`.

# `group_count`

```elixir
@spec group_count(t()) :: non_neg_integer()
```

Total number of groups.

# `init`

```elixir
@spec init([{term(), [term()]}]) :: t()
```

Initialize batch state from a list of `{group_key, items}` tuples.

# `processed_count`

```elixir
@spec processed_count(t()) :: non_neg_integer()
```

Number of groups already processed.

---

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