Public API of the mead runtime: isolated, supervised conversation sessions.
Each session keeps its history across crashes of its server process. The code that produces
the output of a turn is a Mead.Session.TurnHandler, chosen per session.
With config :mead, :storage, directory: ... the turns of every session are also written to
disk, and resume_session/2 brings a stopped session back with the same id and turns. A stored
file is compacted at resume, when a live one grows past compact_after_bytes, and on request
with compact_session/1.
Summary
Functions
Rewrites the stored conversation as one record per turn and returns the bytes before and after.
Stops a session if it runs, removes its stored conversation and forgets its ledger aggregate.
Returns the turns of a session in chronological order.
Lists the stored conversations, newest first.
Starts a session again from the conversation stored under session_id.
Returns what the ledger counted for one session, or {:error, :not_found} for a session that has not completed a turn or was deleted.
Starts a session and returns its id.
Stops a session. Its ledger aggregate stays, so a conversation brought back with
resume_session/2 returns with what it already spent.
Runs one turn and returns its output.
Reads the ledger: the totals over every route, the totals per route and provider, and the most recent turns.
Functions
@spec compact_session(String.t()) :: {:ok, %{bytes_before: non_neg_integer(), bytes_after: non_neg_integer()}} | {:error, :not_found | :corrupt_history | {:persistence, term()}}
Rewrites the stored conversation as one record per turn and returns the bytes before and after.
Nothing is lost, unless config :mead, :storage, max_turns: is set, in which case only that many of the newest turns are kept: history/1 and resume_session/2 see the same turns. A running session is
compacted from memory, a stopped one from its file. Returns {:error, :not_found} without
storage, for an id that is not a session id, and when no file exists yet,
{:error, :corrupt_history} for a damaged file, which is left as it is, and
{:error, {:persistence, reason}} when the rewrite failed and the file is untouched.
Stops a session if it runs, removes its stored conversation and forgets its ledger aggregate.
Returns {:error, :not_found} when there was neither a running session nor a file.
@spec history(String.t()) :: {:ok, [Mead.Session.Turn.t()]} | {:error, :not_found}
Returns the turns of a session in chronological order.
@spec list_sessions() :: {:ok, [%{session_id: String.t(), updated_at: DateTime.t(), running: boolean()}]} | {:error, {:persistence, term()}}
Lists the stored conversations, newest first.
Each entry has the :session_id, the :updated_at of its file, and whether the session
:running now. Only file times are read, so a damaged conversation is listed too and fails at
resume_session/2. Without config :mead, :storage, directory: ... nothing is stored and the
list is empty.
Starts a session again from the conversation stored under session_id.
It takes the options of start_session/1, because the handler and the timeout are not stored.
Turns that were still running when the session ended come back as :interrupted. Needs
config :mead, :storage, directory: ...; without it nothing is stored and the answer is
{:error, :not_found}, which is also the answer for an id with no file or one that is not a
session id. A running session is {:error, :already_running}, and a file damaged anywhere but
its last record is {:error, :corrupt_history}. The file is compacted first; a failed
compaction only logs a warning.
@spec session_usage(String.t(), GenServer.server()) :: {:ok, map()} | {:error, :not_found}
Returns what the ledger counted for one session, or {:error, :not_found} for a session that has not completed a turn or was deleted.
Starts a session and returns its id.
Options
:handler- module implementingMead.Session.TurnHandler; defaults to the:turn_handlerapplication setting, then toMead.Session.EchoHandler.:turn_timeout- milliseconds a single turn may run; defaults to the:turn_timeoutapplication setting, then to 30 seconds.
Raises ArgumentError when config :mead, :storage is malformed, rather than quietly running
without the persistence the operator asked for.
@spec stop_session(String.t()) :: :ok | {:error, :not_found}
Stops a session. Its ledger aggregate stays, so a conversation brought back with
resume_session/2 returns with what it already spent.
The conversation stays on disk when a storage directory is configured; delete_session/1
removes it and forgets its ledger aggregate.
Runs one turn and returns its output.
Options
:route-:auto(the default),:local, or:cloud; read byMead.Routerand ignored by other handlers. Any other value returns{:error, :invalid_route}before a turn is recorded.:tools-:effectalso shows the model tools that have side effects; seeMead.MCP.Policy. Handed to the handler unchanged and absent when not given.:interaction- a{module, context}pair,moduleimplementingMead.Router.Interaction;Mead.Routerthen asks it for permission around every tool call. Anything else returns{:error, :invalid_interaction}before a turn is recorded.
Returns {:error, :not_found} for an unknown session, {:error, :session_stopped} when the
session was stopped with stop_session/1 while the turn was running, and
{:error, :session_crashed} when the session's server died for any other reason.
Reads the ledger: the totals over every route, the totals per route and provider, and the most recent turns.
Options
:recent- how many of the latest turns to include, newest first, from 0 to 100; defaults to 20.:ledger- the ledger to read; defaults toMead.Ledger.
It never changes anything. The totals, the routes and the recent turns are three separate reads of the live tables, so a turn counted between them can show in one and not in another; the result is not a single snapshot. When the ledger is not running it exits, as the ledger accessors do.