Read-only facade for querying agent session state from extensions.
Extensions use this module instead of importing MingaAgent.Session
or MingaAgent.SessionManager directly. The facade returns plain maps
with a stable shape, shielding extensions from internal refactors.
All functions are safe to call with dead PIDs or when no sessions exist; they return empty results rather than crashing.
Usage
sessions = Minga.Extension.AgentAPI.list_sessions()
# => [%{id: "1", pid: #PID<0.1234.0>, status: :thinking, ...}, ...]
info = Minga.Extension.AgentAPI.session_info(pid)
# => {:ok, %{id: "1", status: :thinking, cost: 0.042, ...}}
Minga.Extension.AgentAPI.subscribe()
# subscribes calling process to agent lifecycle events
Summary
Types
Detailed info for a specific agent session.
Agent session status.
Summary of an active agent session.
Functions
Lists all active agent sessions with a summary for each.
Returns detailed info for a specific session by PID.
Subscribes the calling process to agent lifecycle events.
Subscribes the calling process to agent edit events.
Types
@type session_info() :: %{ id: String.t(), pid: pid(), status: session_status(), label: String.t(), model: String.t(), active_tool: String.t() | nil, created_at: DateTime.t(), cost: float(), input_tokens: non_neg_integer(), output_tokens: non_neg_integer(), turn_count: non_neg_integer(), files_touched: [String.t()] }
Detailed info for a specific agent session.
@type session_status() :: :idle | :plan | :thinking | :tool_executing | :error
Agent session status.
@type session_summary() :: %{ id: String.t(), pid: pid(), status: session_status(), label: String.t(), model: String.t(), active_tool: String.t() | nil, created_at: DateTime.t() }
Summary of an active agent session.
Functions
@spec list_sessions(keyword()) :: [session_summary()]
Lists all active agent sessions with a summary for each.
Returns an empty list if no sessions are running or the session manager is unavailable.
@spec session_info( pid(), keyword() ) :: {:ok, session_info()} | {:error, :not_found}
Returns detailed info for a specific session by PID.
Includes cost, token usage, and turn count in addition to the
summary fields. Returns {:error, :not_found} if the PID is dead
or not a known session.
@spec subscribe() :: :ok
Subscribes the calling process to agent lifecycle events.
After calling this, the process receives messages in the standard event bus format:
{:minga_event, :agent_session_stopped, %MingaAgent.SessionManager.SessionStoppedEvent{session_id: id, pid: pid, reason: reason}}{:minga_event, :agent_hook, %Minga.Events.AgentHookEvent{event: event, phase: phase, tool_name: name, ...}}
Subscribe to :buffer_changed separately via subscribe_edits/0 if you
need edit-level granularity (e.g., for ghost cursors tracking edit positions).
Note: :agent_session_started and :agent_status_changed events will be
added incrementally as the internal event infrastructure expands. For now,
extensions can poll list_sessions/0 or use :agent_hook phase transitions
to infer session activity.
@spec subscribe_edits() :: :ok
Subscribes the calling process to agent edit events.
After calling this, the process receives :buffer_changed events
for all buffer edits, including agent-sourced ones. To isolate
agent edits, pattern-match on the source field inside the struct:
receive do
{:minga_event, :buffer_changed, %Minga.Events.BufferChangedEvent{source: {:agent, session_pid, tool_call_id}} = event} ->
# this edit came from an agent session
end