Database operations for an agent's conversation history.
All functions that persist or load messages from the session SQLite database
live here. Planck.Agent calls these helpers and applies the returned data
to its own state — there is no state mutation in this module.
Summary
Functions
Persist any in-memory messages that have not yet been written to the session.
Load the message history for agent_id from session_id.
Persist msg to the session and return it with its database ID set.
Save accumulated usage and cost for the agent to the session metadata store.
Remove the last row from rows if it is an orphaned tool-call turn.
Functions
@spec flush_unpersisted(String.t() | nil, String.t(), [Planck.Agent.Message.t()]) :: :flushed | :noop
Persist any in-memory messages that have not yet been written to the session.
Unpersisted messages are identified by a binary (UUID) id — messages written
to the DB receive an integer id. Returns :flushed when at least one message
was written, :noop when all messages were already persisted.
Always returns :noop for ephemeral agents (session_id: nil).
@spec load_messages(String.t(), String.t(), keyword()) :: {:ok, [Planck.Agent.Message.t()]} | :error
Load the message history for agent_id from session_id.
Returns {:ok, messages} on success, or :error when the session is
unavailable.
Pass strip_orphans: true to remove the last message if it is an assistant
turn with unanswered tool calls — this repairs state after a crash.
@spec persist_message(String.t() | nil, String.t(), Planck.Agent.Message.t()) :: Planck.Agent.Message.t()
Persist msg to the session and return it with its database ID set.
Returns msg unchanged for ephemeral agents (session_id: nil) or when
the session append fails.
@spec persist_usage(String.t() | nil, String.t(), Planck.Agent.Usage.t()) :: :ok
Save accumulated usage and cost for the agent to the session metadata store.
No-op for ephemeral agents (session_id: nil).
Remove the last row from rows if it is an orphaned tool-call turn.
A turn is orphaned when the last assistant message contains tool calls but
has no following tool-result message — the agent crashed mid-execution.
The orphan is also truncated from the database when session_id is non-nil.