MingaAgent.Providers.Native (Minga v0.1.0)

Copy Markdown View Source

Native Elixir agent provider backed by ReqLLM.

It runs entirely inside the BEAM and supports any ReqLLM-backed provider that has an installed exact text route. Session resolves a model, protocol, endpoint, credential identity, reasoning policy, limits, and capabilities before this provider starts. Native executes that immutable selection without reparsing a model name.

The provider consumes immutable Session-owned continuation snapshots, executes tools locally, and emits Agent.Event structs to its subscriber (the Agent.Session) for rendering in the chat panel.

Architecture

When send_prompt/2 is called, the provider spawns a linked Task to run the agent turn loop. The loop:

  1. Calls ReqLLM.stream_text/3 with the conversation history and tools
  2. Uses StreamResponse.process_stream/2 with callbacks to emit events in real time as chunks arrive
  3. If the response contains tool calls, executes each tool, appends results to the conversation context, and loops back to step 1
  4. If no tool calls, the turn is complete

The task sends events to the GenServer via send/2, and the GenServer forwards them to the subscriber. This keeps the GenServer responsive for abort and state queries while streaming is in progress.

Summary

Types

Function that executes a matching hook.

Captures the immutable parameters for one agent turn loop invocation.

Internal state for the native provider.

Functions

Returns the agent hooks from the provider's config.

Returns the changeset PID, or nil.

Returns a specification to start this module under a supervisor.

Manually compacts an immutable continuation snapshot.

Compacts messages only when they exceed the configured context threshold.

Continues from an interrupted stream using a Session-owned request snapshot.

Returns the PID of the fork store, or nil if not active.

Returns the project view associated with this provider, or nil.

Refreshes the project view and rebuilds file tools around the new overlay.

Returns the current tool list registered with this provider.

Types

hook_runner()

Function that executes a matching hook.

llm_client()

@type llm_client() :: (LLMDB.Model.t(), [ReqLLM.Message.t()], keyword() ->
                   {:ok, ReqLLM.StreamResponse.t()} | {:error, term()})

loop_ctx()

Captures the immutable parameters for one agent turn loop invocation.

state()

@type state() :: %{
  subscriber: pid(),
  subscriber_ref: reference(),
  linked_parent: pid() | nil,
  config: MingaAgent.Config.t(),
  selection: MingaAgent.ModelSelection.t(),
  session_manager: pid() | nil,
  active_request: MingaAgent.Session.Request.t() | nil,
  tools: [term()],
  project_root: String.t(),
  project_view: MingaAgent.ProjectView.t() | nil,
  max_retries: non_neg_integer(),
  credential_opts: keyword(),
  llm_client: llm_client(),
  hook_runner: hook_runner(),
  task: Task.t() | nil,
  streaming: boolean(),
  interrupted: boolean(),
  active_skills: [MingaAgent.Skills.skill()],
  internal_state: MingaAgent.InternalState.t(),
  max_turns: pos_integer(),
  max_cost: float() | nil,
  session_cost: float(),
  fork_store: pid() | nil,
  changeset: pid() | nil,
  base_tools: [term()],
  mcp_tools: [term()],
  internal_tools: [term()],
  tool_metadata: map(),
  custom_tool_declarations: [ReqLLM.Tool.t() | MingaAgent.Tool.Spec.t()],
  custom_tools?: boolean(),
  configured_mcp_configs: [MingaAgent.MCP.ServerConfig.t()],
  mcp_configs: [MingaAgent.MCP.ServerConfig.t()],
  mcp_client_opts: keyword(),
  mcp_enabled_override: boolean() | nil,
  mcp_errors: %{required(String.t()) => String.t()},
  mcp_registry: MingaAgent.MCP.Registry.t() | nil,
  read_only?: boolean(),
  tool_allowlist: :all | [String.t()],
  tool_workers: MapSet.t(pid())
}

Internal state for the native provider.

Functions

agent_hooks(pid)

@spec agent_hooks(GenServer.server()) :: [MingaAgent.Hooks.Hook.t()]

Returns the agent hooks from the provider's config.

changeset(pid)

@spec changeset(GenServer.server()) :: pid() | nil

Returns the changeset PID, or nil.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

compact(pid, messages)

@spec compact(GenServer.server(), [ReqLLM.Message.t()]) ::
  {:ok, [ReqLLM.Message.t()], String.t()} | {:error, String.t()}

Manually compacts an immutable continuation snapshot.

compact(pid, messages, opts)

@spec compact(GenServer.server(), [ReqLLM.Message.t()], keyword()) ::
  {:ok, [ReqLLM.Message.t()], String.t()} | {:error, String.t()}

Compacts messages only when they exceed the configured context threshold.

continue(pid, request)

@spec continue(GenServer.server(), MingaAgent.Session.Request.t()) ::
  :ok | {:error, term()}

Continues from an interrupted stream using a Session-owned request snapshot.

detect_project_root()

See Minga.Project.resolve_root/0.

fork_store(pid)

@spec fork_store(GenServer.server()) :: pid() | nil

Returns the PID of the fork store, or nil if not active.

project_view(pid)

@spec project_view(GenServer.server()) :: MingaAgent.ProjectView.t() | nil

Returns the project view associated with this provider, or nil.

refresh_project_view(pid, project_view)

@spec refresh_project_view(GenServer.server(), MingaAgent.ProjectView.t() | nil) ::
  :ok | {:error, term()}

Refreshes the project view and rebuilds file tools around the new overlay.

tools(pid)

@spec tools(GenServer.server()) :: [ReqLLM.Tool.t()]

Returns the current tool list registered with this provider.