# `Minga.Extension.AgentAPI`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga/extension/agent_api.ex#L1)

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

# `session_info`

```elixir
@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`

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

Agent session status.

# `session_summary`

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

# `list_sessions`

```elixir
@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`

```elixir
@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`

```elixir
@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`

```elixir
@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

---

*Consult [api-reference.md](api-reference.md) for complete listing*
