GenStateMachine managing the lifecycle of a memory session.
States: :idle, :collecting, :extracting, :failed, :ready.
Extraction is spawned under a Task.Supervisor via async_nolink,
keeping the session responsive while LLM work happens in the background.
Failed state preserves the closed episode for retry.
Summary
Functions
Appends an observation-action pair to the current episode. Blocks until the append completes or the timeout expires.
Like append/3 but returns immediately. Accepts an optional callback that
receives :ok or {:error, reason} when the append finishes.
Returns a specification to start this module under a supervisor.
Closes the current episode and starts asynchronous extraction.
Asynchronous close. Returns immediately or queues when busy.
The optional callback receives {:ok, :closed} or {:error, reason}.
Commits the session result. In :ready state, applies the extracted changeset
to the MemoryStore and transitions to :idle. In :failed state, retries
the extraction by re-spawning the extraction task.
Asynchronous commit. Returns immediately with :ok when the session is idle
or ready, or queues the operation when extraction is in progress. The optional
callback receives {:ok, :committed} or {:error, reason} when the op runs.
Discards the extraction result and returns to :idle.
Asynchronous discard. Returns immediately or queues when busy.
The optional callback receives {:ok, :discarded} or {:error, reason}.
Returns session context for use by MemoryStore.recall_in_context.
Like get_context/1 but looks up the session in the given registry.
Returns the unique session ID.
Opens a new episode with the given goal, transitioning from :idle to :collecting.
Asynchronous start_episode. Returns immediately or queues when busy.
The optional callback receives {:ok, :started} or {:error, reason}.
Returns the current state atom (:idle, :collecting, :extracting, :ready, :failed).
Types
@type append_caller() :: {:reply, GenServer.from()} | {:callback, (append_result() -> any())}
@type append_result() :: :ok | {:error, Mnemosyne.Errors.error()}
@type op_callback() :: ({:ok, term()} | {:error, Mnemosyne.Errors.error()} -> any()) | nil
@type state() :: :idle | :collecting | :extracting | :ready | :failed
@type t() :: %Mnemosyne.Session{ append_caller: append_caller() | nil, append_queue: :queue.queue(), append_task: reference() | nil, changeset: Mnemosyne.Graph.Changeset.t() | nil, committed_step_indices: MapSet.t(non_neg_integer()), config: Mnemosyne.Config.t() | nil, embedding: module() | nil, episode: Mnemosyne.Pipeline.Episode.t() | nil, extraction_task: reference() | nil, flush_timer: reference() | nil, flush_triggered: %{required(String.t()) => true}, id: String.t() | nil, llm: module() | nil, memory_store: GenServer.server() | nil, notifier: module() | nil, pending_ops: :queue.queue(), prev_trajectory_id: String.t() | nil, registry: module() | nil, repo_id: String.t() | nil, session_timer: reference() | nil, stopping: boolean(), task_supervisor: module() | nil, trajectory_tasks: %{ required(reference()) => {String.t(), [non_neg_integer()]} } }
Functions
@spec append(GenServer.server(), String.t(), String.t()) :: :ok | {:error, Mnemosyne.Errors.error()}
Appends an observation-action pair to the current episode. Blocks until the append completes or the timeout expires.
@spec append_async( GenServer.server(), String.t(), String.t(), (append_result() -> any()) | nil ) :: :ok
Like append/3 but returns immediately. Accepts an optional callback that
receives :ok or {:error, reason} when the append finishes.
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec close(GenServer.server()) :: :ok | {:error, Mnemosyne.Errors.error()}
Closes the current episode and starts asynchronous extraction.
@spec close_async(GenServer.server(), op_callback()) :: :ok | {:error, Mnemosyne.Errors.Framework.SessionError.t()}
Asynchronous close. Returns immediately or queues when busy.
The optional callback receives {:ok, :closed} or {:error, reason}.
@spec commit(GenServer.server()) :: :ok | {:error, Mnemosyne.Errors.error()}
Commits the session result. In :ready state, applies the extracted changeset
to the MemoryStore and transitions to :idle. In :failed state, retries
the extraction by re-spawning the extraction task.
@spec commit_async(GenServer.server(), op_callback()) :: :ok | {:error, Mnemosyne.Errors.Framework.SessionError.t()}
Asynchronous commit. Returns immediately with :ok when the session is idle
or ready, or queues the operation when extraction is in progress. The optional
callback receives {:ok, :committed} or {:error, reason} when the op runs.
@spec discard(GenServer.server()) :: :ok | {:error, Mnemosyne.Errors.Framework.SessionError.t()}
Discards the extraction result and returns to :idle.
@spec discard_async(GenServer.server(), op_callback()) :: :ok | {:error, Mnemosyne.Errors.Framework.SessionError.t()}
Asynchronous discard. Returns immediately or queues when busy.
The optional callback receives {:ok, :discarded} or {:error, reason}.
@spec get_context(GenServer.server() | String.t()) :: {:ok, map() | nil}
Returns session context for use by MemoryStore.recall_in_context.
Accepts a pid/name for direct calls, or a string session_id looked up
via Mnemosyne.Registry (the default production registry).
Returns {:ok, %{goal: ..., recent_steps: [...]}} or {:ok, nil} when idle.
Like get_context/1 but looks up the session in the given registry.
@spec id(GenServer.server()) :: String.t()
Returns the unique session ID.
@spec start_episode(GenServer.server(), String.t()) :: :ok | {:error, Mnemosyne.Errors.Framework.SessionError.t()}
Opens a new episode with the given goal, transitioning from :idle to :collecting.
@spec start_episode_async(GenServer.server(), String.t(), op_callback()) :: :ok | {:error, Mnemosyne.Errors.Framework.SessionError.t()}
Asynchronous start_episode. Returns immediately or queues when busy.
The optional callback receives {:ok, :started} or {:error, reason}.
@spec state(GenServer.server()) :: state()
Returns the current state atom (:idle, :collecting, :extracting, :ready, :failed).