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.
Manager-owned remote identity is stored separately under .remote_tokens/.
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.
Summary
Types
Full session data for save/load.
Session metadata for the picker (without full message content).
Functions
Deletes all saved transcripts before explicitly dropping each artifact record.
Durably deletes a transcript before explicitly dropping its retained artifact record.
Establishes manager-owned remote session identity.
Lists all saved sessions as metadata (without full messages).
Loads a versioned, lossless session snapshot.
Loads a session and reconciles retained snapshot pin generations.
Reads an unversioned or version-one display-only record for explicit one-way import.
Prunes session transcripts older than days days.
Saves a session to disk.
Returns the sessions directory path.
Types
@type session_data() :: %{ :id => String.t(), :timestamp => String.t(), :model_name => String.t(), :messages => [MingaAgent.Message.t()], :usage => MingaAgent.TurnUsage.t(), :continuation => MingaAgent.Session.Continuation.t(), optional(:model_selection) => MingaAgent.ModelSelection.t() | MingaAgent.ModelSelection.Stored.t() | nil, optional(:selection_intent) => map(), optional(:last_message_at) => String.t(), optional(:title) => String.t(), optional(:provider_name) => String.t(), optional(:branches) => [MingaAgent.Branch.t()], optional(:message_ids) => [pos_integer()], optional(:pinned_ids) => MapSet.t(pos_integer()), optional(:memory) => String.t() | nil }
Full session data for save/load.
@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(), continuation_kind: :lossless | :legacy_reconstructed | :legacy_import_required }
Session metadata for the picker (without full message content).
Functions
Deletes all saved transcripts before explicitly dropping each artifact record.
Durably deletes a transcript before explicitly dropping its retained artifact record.
@spec establish_remote_token(String.t(), String.t(), String.t() | nil) :: {:ok, String.t()} | {:error, term()}
Establishes manager-owned remote session identity.
Existing canonical identity wins over legacy transcript identity and the candidate. A new identity is persisted before it is returned.
@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.
@spec load(String.t(), String.t() | nil) :: {:ok, session_data()} | {:error, term()}
Loads a versioned, lossless session snapshot.
Legacy display-only records are rejected until the caller explicitly uses
load_legacy/2; unknown future versions are never guessed.
@spec load(String.t(), String.t() | nil, keyword()) :: {:ok, session_data()} | {:error, term()}
Loads a session and reconciles retained snapshot pin generations.
@spec load_legacy(String.t(), String.t() | nil) :: {:ok, session_data()} | {:error, term()}
Reads an unversioned or version-one display-only record for explicit one-way import.
@spec prune(non_neg_integer(), String.t() | nil, keyword()) :: non_neg_integer()
Prunes session transcripts older than days days.
Returns the number durably removed before their artifact records were explicitly dropped. Durable remote identities are retained.
@spec save(session_data(), String.t() | nil, keyword()) :: :ok | {:error, term()}
Saves a session to disk.
Candidate artifact references are pinned before the private temporary file is written. The prior snapshot pin is released only after rename and parent directory synchronization make the candidate durable.
Returns the sessions directory path.