# `Minga.Buffer.UndoHistory`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga/buffer/undo_history.ex#L1)

Undo and redo history for a buffer document.

The buffer process owns the live document and version counter. This struct remembers the patches needed to move backward and forward through document history, including the source of each edit for diagnostics and attribution.

This module is pure state. It does not mark buffers dirty, broadcast events, or mutate documents outside applying returned patches to produce a restore document.

# `edit_source`

```elixir
@type edit_source() :: Minga.Buffer.EditSource.undo_source()
```

# `entry`

```elixir
@type entry() :: {version(), patches(), edit_source()}
```

# `patches`

```elixir
@type patches() :: [Minga.Buffer.UndoPatch.t(), ...]
```

# `t`

```elixir
@opaque t()
```

# `version`

```elixir
@type version() :: non_neg_integer()
```

# `break_coalescing`

```elixir
@spec break_coalescing(t()) :: t()
```

Resets the coalescing timer so the next recorded edit creates a new undo entry.

# `clear`

```elixir
@spec clear(t()) :: t()
```

Clears undo and redo entries and resets coalescing state.

# `coalesce_ms`

```elixir
@spec coalesce_ms() :: pos_integer()
```

Returns the coalescing window in milliseconds.

# `last_redo_source`

```elixir
@spec last_redo_source(t()) :: edit_source() | nil
```

Returns the source of the most recent redo entry, or `nil` if redo is unavailable.

# `last_undo_source`

```elixir
@spec last_undo_source(t()) :: edit_source() | nil
```

Returns the source of the most recent undo entry, or `nil` if undo is unavailable.

# `new`

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

Creates an empty undo history.

# `record_edit`

```elixir
@spec record_edit(t(), version(), Minga.Buffer.UndoPatch.t(), edit_source()) :: t()
```

Records an undo patch, coalescing rapid edits into one history entry.

# `record_edit_batch`

```elixir
@spec record_edit_batch(t(), version(), patches(), edit_source()) :: t()
```

Records one undo entry containing all patches in the batch.

# `record_edit_force`

```elixir
@spec record_edit_force(t(), version(), Minga.Buffer.UndoPatch.t(), edit_source()) ::
  t()
```

Records an undo patch without time-based coalescing.

# `redo`

```elixir
@spec redo(t(), version(), Minga.Buffer.Document.t()) ::
  {:ok, Minga.Buffer.UndoHistory.Restore.t(), t()} | :empty
```

Returns the next document/version and updates history, or `:empty` when redo is unavailable.

# `undo`

```elixir
@spec undo(t(), version(), Minga.Buffer.Document.t()) ::
  {:ok, Minga.Buffer.UndoHistory.Restore.t(), t()} | :empty
```

Returns the previous document/version and updates history, or `:empty` when undo is unavailable.

# `undo_agent_session`

```elixir
@spec undo_agent_session(t(), version(), Minga.Buffer.Document.t()) ::
  {:ok, Minga.Buffer.UndoHistory.Restore.t(), t(), pos_integer()} | :empty
```

Undoes all consecutive `:agent`-sourced entries from the top of the undo stack.

Walks backward through the undo stack, popping every entry whose source is `:agent`, applying its patches to roll back the document, and pushing corresponding redo entries. Stops at the first non-agent entry or when the stack is empty.

Returns `{:ok, restore, updated_history, undone_count}` with the final document state after all agent entries are reversed, or `:empty` when no agent entries are on top.

---

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