# `MingaAgent.SessionStore`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga_agent/session_store.ex#L1)

Persists agent conversations to disk as JSON files.

Each session is saved as `{session_id}.json` in the sessions directory
(`~/.config/minga/agent/sessions/` by default). Files are written
atomically via a temp file + rename to avoid corruption on crash.

The store is stateless: all functions operate directly on the filesystem.
The `Session` GenServer calls `save/2` on a debounced timer, and the
picker calls `list/0` to scan the directory for past sessions.

# `session_data`

```elixir
@type session_data() :: %{
  :id =&gt; String.t(),
  :timestamp =&gt; String.t(),
  :model_name =&gt; String.t(),
  :messages =&gt; [MingaAgent.Message.t()],
  :usage =&gt; MingaAgent.TurnUsage.t(),
  optional(:last_message_at) =&gt; String.t(),
  optional(:title) =&gt; String.t(),
  optional(:remote_token) =&gt; String.t() | nil,
  optional(:provider_name) =&gt; String.t(),
  optional(:branches) =&gt; [MingaAgent.Branch.t()],
  optional(:message_ids) =&gt; [pos_integer()],
  optional(:pinned_ids) =&gt; MapSet.t(pos_integer()),
  optional(:memory) =&gt; String.t() | nil
}
```

Full session data for save/load.

# `session_meta`

```elixir
@type session_meta() :: %{
  id: String.t(),
  timestamp: String.t(),
  last_message_at: String.t(),
  title: String.t(),
  model_name: String.t(),
  provider_name: String.t(),
  preview: String.t(),
  recent_messages: String.t(),
  message_count: non_neg_integer(),
  turn_count: non_neg_integer(),
  cost: float()
}
```

Session metadata for the picker (without full message content).

# `clear_all`

```elixir
@spec clear_all(String.t() | nil) :: :ok
```

Deletes all saved sessions.

# `delete`

```elixir
@spec delete(String.t(), String.t() | nil) :: :ok | {:error, term()}
```

Deletes a saved session.

# `list`

```elixir
@spec list(String.t() | nil) :: [session_meta()]
```

Lists all saved sessions as metadata (without full messages).

Returns sessions sorted by last message timestamp, most recent first.

# `load`

```elixir
@spec load(String.t(), String.t() | nil) :: {:ok, session_data()} | {:error, term()}
```

Loads a session from disk.

Returns `{:ok, session_data}` or `{:error, reason}`.

# `prune`

```elixir
@spec prune(non_neg_integer(), String.t() | nil) :: non_neg_integer()
```

Prunes sessions older than `days` days.

Returns the number of sessions deleted.

# `save`

```elixir
@spec save(session_data(), String.t() | nil) :: :ok | {:error, term()}
```

Saves a session to disk.

Creates the sessions directory if it doesn't exist. Writes atomically
via a temp file to avoid corruption.

# `sessions_dir`

```elixir
@spec sessions_dir(String.t() | nil) :: String.t()
```

Returns the sessions directory path.

---

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