Raxol.Agent.LSPContext (Raxol Agent v2.6.0)

Copy Markdown View Source

LSP context enrichment for agent prompts.

Manages a Language Server Protocol connection and extracts diagnostics, symbols, and hover info to build context maps that agents can inject into their LLM prompts.

Usage

# Start an LSP client
{:ok, client} = LSPContext.start_link(
  command: "elixir-ls",
  args: ["--stdio"],
  root_uri: "file:///path/to/project"
)

# Get diagnostics for a file
{:ok, diags} = LSPContext.diagnostics(client, "file:///path/to/project/lib/foo.ex")

# Get symbols in a file
{:ok, symbols} = LSPContext.symbols(client, "file:///path/to/project/lib/foo.ex")

# Build a context string for agent prompts
context = LSPContext.format_context(client, "file:///path/to/project/lib/foo.ex")

Protocol

Uses JSON-RPC 2.0 over stdio, the same transport as the MCP client. The LSP server is spawned as a Port and communicated with via newline-delimited JSON-RPC messages with Content-Length headers.

Summary

Functions

Returns a specification to start this module under a supervisor.

Get diagnostics for a file URI. Returns cached diagnostics pushed by the server.

Build a formatted context string for agent prompts.

Build a context string from pre-fetched data (pure function).

Get hover information at a position in a file.

Start an LSP context client linked to the calling process.

Get the client status.

Stop the LSP server and client.

Get document symbols for a file URI.

Types

diagnostic()

@type diagnostic() :: %{
  uri: String.t(),
  range: range(),
  severity: :error | :warning | :info | :hint,
  message: String.t(),
  source: String.t() | nil
}

range()

@type range() :: %{
  start: %{line: non_neg_integer(), character: non_neg_integer()},
  end: %{line: non_neg_integer(), character: non_neg_integer()}
}

symbol()

@type symbol() :: %{
  name: String.t(),
  kind: atom(),
  range: range(),
  children: [symbol()]
}

t()

@type t() :: %Raxol.Agent.LSPContext{
  args: [String.t()],
  buffer: binary(),
  command: String.t(),
  diagnostics_cache: %{required(String.t()) => [diagnostic()]},
  env: [{String.t(), String.t()}],
  next_id: pos_integer(),
  pending: %{required(pos_integer()) => {GenServer.from(), atom()}},
  port: port() | nil,
  root_uri: String.t(),
  status: :starting | :initializing | :ready | :closed
}

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

diagnostics(server, uri)

@spec diagnostics(GenServer.server(), String.t()) ::
  {:ok, [diagnostic()]} | {:error, term()}

Get diagnostics for a file URI. Returns cached diagnostics pushed by the server.

format_context(server, uri)

@spec format_context(GenServer.server(), String.t()) :: String.t()

Build a formatted context string for agent prompts.

Combines diagnostics and symbols for the given URI into a structured text block suitable for LLM consumption.

format_context_from_data(uri, diagnostics, symbols)

@spec format_context_from_data(String.t(), [diagnostic()], [symbol()]) :: String.t()

Build a context string from pre-fetched data (pure function).

Useful when you already have diagnostics and symbols and don't need to query the server.

handle_manager_cast(msg, state)

Callback implementation for Raxol.Core.Behaviours.BaseManager.handle_manager_cast/2.

hover(server, uri, line, character)

@spec hover(GenServer.server(), String.t(), non_neg_integer(), non_neg_integer()) ::
  {:ok, String.t() | nil} | {:error, term()}

Get hover information at a position in a file.

start_link(init_opts \\ [])

@spec start_link(keyword()) :: GenServer.on_start()

Start an LSP context client linked to the calling process.

status(server)

@spec status(GenServer.server()) :: map()

Get the client status.

stop(server)

@spec stop(GenServer.server()) :: :ok

Stop the LSP server and client.

symbols(server, uri)

@spec symbols(GenServer.server(), String.t()) :: {:ok, [symbol()]} | {:error, term()}

Get document symbols for a file URI.