Minga.Extension.AgentAPI (Minga v0.1.0)

Copy Markdown View Source

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

session_info()

@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.

session_status()

@type session_status() :: :idle | :plan | :thinking | :tool_executing | :error

Agent session status.

session_summary()

@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

list_sessions(opts \\ [])

@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.

session_info(pid, opts \\ [])

@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.

subscribe()

@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.

subscribe_edits()

@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