lsp

package
v1.2.0-alpha.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 25, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Overview

Package lsp provides Language Server Protocol integration for evva.

The lsp_request tool (deferred) allows the agent to query LSP servers for semantic code intelligence: go-to-definition, find references, hover, and document symbols. Servers are started lazily on first use and managed via the daemon system.

See docs/roadmap/lsp.md for architecture and implementation plan.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DiscoverServers

func DiscoverServers(workdir string) map[string]LspServerConfig

DiscoverServers scans the workdir for project markers and checks PATH for matching LSP servers. Returns configs for usable servers.

func FormatDiagnosticsReminder

func FormatDiagnosticsReminder(diags []PendingDiagnostic) string

FormatDiagnosticsReminder renders diagnostics as a <system-reminder> block.

func IsNotFoundError

func IsNotFoundError(err error) bool

IsNotFoundError reports whether err indicates the server binary was not found.

func Names

func Names() []tools.ToolName

Names lists every tool name this package contributes.

func NewTool

func NewTool(mgr *Manager, workDir string) *lspTool

NewTool creates an lspTool bound to the given manager.

func SuggestServerForExt

func SuggestServerForExt(ext string) string

SuggestServerForExt returns the name of a known server that handles the given extension, or "" if none is known.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a JSON-RPC 2.0 client that speaks the LSP framing protocol (Content-Length header + JSON body) over stdin/stdout of a child process.

func Start

func Start(ctx context.Context, command string, args []string, logger *slog.Logger) (*Client, error)

Start spawns the LSP server process and starts the reader goroutine. The caller owns the returned Client and must call Close to clean up.

func (*Client) Close

func (c *Client) Close() error

Close sends a graceful shutdown sequence: shutdown request → exit notification → kill process. Callers should use Server.Stop instead of calling this directly — Server manages the handshake timeout.

func (*Client) Notify

func (c *Client) Notify(ctx context.Context, method string, params any) error

Notify sends a JSON-RPC notification (no id, no response expected).

func (*Client) OnNotify

func (c *Client) OnNotify(method string, handler NotificationHandler)

OnNotify registers a handler for incoming notifications. Handlers are called synchronously from the reader goroutine — keep them fast.

func (*Client) Process

func (c *Client) Process() *os.Process

Process returns the underlying os.Process for signal operations.

func (*Client) Request

func (c *Client) Request(ctx context.Context, method string, params any) (json.RawMessage, error)

Request sends a JSON-RPC request and blocks until the response arrives or ctx expires. Returns the raw JSON result field or an error.

type DiagnosticRegistry

type DiagnosticRegistry struct {
	// contains filtered or unexported fields
}

DiagnosticRegistry collects, deduplicates, and drains LSP diagnostics.

func NewDiagnosticRegistry

func NewDiagnosticRegistry() *DiagnosticRegistry

NewDiagnosticRegistry creates a registry with default limits.

func (*DiagnosticRegistry) ClearFile

func (r *DiagnosticRegistry) ClearFile(fileURI string)

ClearFile removes pending diagnostics for a file and marks their identity keys as delivered (so they don't re-appear if the server re-sends them).

func (*DiagnosticRegistry) Drain

Drain returns all pending diagnostics and clears the queue.

func (*DiagnosticRegistry) Register

func (r *DiagnosticRegistry) Register(serverName, fileURI string, diags []protocol.Diagnostic)

Register adds diagnostics for a file. Already-delivered diagnostics (matched by identity key) are dropped. Per-file and total caps are enforced.

type LspConfig

type LspConfig struct {
	Servers map[string]LspServerConfig `yaml:"servers"`
}

LspConfig is the top-level config file shape.

func LoadConfig

func LoadConfig(projectDir, userHome string) (*LspConfig, error)

LoadConfig reads project-level .evva/lsp_servers.yml with fallback to user-level ~/.evva/lsp_servers.yml. Project-level entries override user-level for the same server name. Returns a default empty config when neither file exists.

type LspServerConfig

type LspServerConfig struct {
	Command        string            `yaml:"command"`
	Args           []string          `yaml:"args"`
	Extensions     map[string]string `yaml:"extensions"` // ".go" → "go", ".ts" → "typescript"
	Env            map[string]string `yaml:"env"`
	StartupTimeout string            `yaml:"startupTimeout"` // "30s"
	MaxRestarts    int               `yaml:"maxRestarts"`    // default 3
}

LspServerConfig describes one LSP server to manage.

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager routes files to LSP servers based on extension and manages server lifecycles (lazy start, document sync, shutdown).

func NewManager

func NewManager(configs map[string]LspServerConfig, rootURI string, logger *slog.Logger) *Manager

NewManager creates a Manager from a list of server configs. Servers are registered but not started — they start lazily on first EnsureServerStarted.

func (*Manager) CloseFile

func (m *Manager) CloseFile(ctx context.Context, filePath string) error

CloseFile sends textDocument/didClose for a previously opened file.

func (*Manager) DrainDiagnostics

func (m *Manager) DrainDiagnostics() []PendingDiagnostic

DrainDiagnostics returns all pending diagnostics and clears the queue. Called by the agent loop at the start of each iteration.

func (*Manager) EnsureServerStarted

func (m *Manager) EnsureServerStarted(ctx context.Context, filePath string) (*Server, error)

EnsureServerStarted lazily starts the server responsible for filePath. Uses singleflight to prevent duplicate starts — all concurrent callers for the same server share one start attempt and result.

func (*Manager) FirstExtensionFor

func (m *Manager) FirstExtensionFor(serverName string) string

FirstExtensionFor returns the first file extension (including leading dot) mapped to the given server name, or "" if none is mapped.

func (*Manager) NotifyFileChanged

func (m *Manager) NotifyFileChanged(filePath string)

NotifyFileChanged clears diagnostics for a file. Call this after external file modifications (write, edit, bash) to invalidate stale diagnostics.

func (*Manager) OpenFile

func (m *Manager) OpenFile(ctx context.Context, filePath, content string) error

OpenFile sends textDocument/didOpen to the server responsible for filePath and tracks the open state.

func (*Manager) ServerForFile

func (m *Manager) ServerForFile(filePath string) (*Server, bool)

ServerForFile returns the server responsible for the given file path and whether one was found.

func (*Manager) Servers

func (m *Manager) Servers() []string

Servers returns all managed server names.

func (*Manager) SetDaemonState

func (m *Manager) SetDaemonState(ds *daemon.DaemonState)

SetDaemonState installs the daemon catalog for LSP lifecycle tracking. When set, LSP servers are registered as daemons on start so daemon_list and daemon_output can introspect their state.

func (*Manager) Shutdown

func (m *Manager) Shutdown(ctx context.Context) error

Shutdown stops all managed servers gracefully.

type NotificationHandler

type NotificationHandler func(params json.RawMessage)

NotificationHandler receives incoming notifications from the server.

type PendingDiagnostic

type PendingDiagnostic struct {
	ServerName  string
	FileURI     string
	FilePath    string
	Diagnostics []protocol.Diagnostic
}

PendingDiagnostic holds diagnostics queued for delivery for a single file.

type Server

type Server struct {
	Name   string
	Config LspServerConfig
	// contains filtered or unexported fields
}

Server wraps a single LSP server process with a state machine.

func NewServer

func NewServer(name string, cfg LspServerConfig, rootURI string, logger *slog.Logger) *Server

NewServer creates a Server from the given config. The server is not started until Start is called.

func (*Server) Capabilities

func (s *Server) Capabilities() protocol.ServerCapabilities

Capabilities returns the server's advertised capabilities.

func (*Server) IsHealthy

func (s *Server) IsHealthy() bool

IsHealthy returns true when the server is in StateRunning.

func (*Server) MaxRestarts

func (s *Server) MaxRestarts() int

MaxRestarts returns the configured restart limit.

func (*Server) Notify

func (s *Server) Notify(ctx context.Context, method string, params any) error

Notify sends a notification to the server.

func (*Server) OnNotify

func (s *Server) OnNotify(method string, handler NotificationHandler)

OnNotify registers a notification handler on the underlying client.

func (*Server) Request

func (s *Server) Request(ctx context.Context, method string, params any) (json.RawMessage, error)

Request sends a typed LSP request and returns the raw JSON result.

func (*Server) RestartCount

func (s *Server) RestartCount() int

RestartCount returns the number of restarts since the last successful start.

func (*Server) SetDiagHandler

func (s *Server) SetDiagHandler(h NotificationHandler)

SetDiagHandler stores the publishDiagnostics handler for re-registration when the client is created in Start(). Called by Manager at construction.

func (*Server) Start

func (s *Server) Start(ctx context.Context) error

Start spawns the LSP process, performs the initialize handshake, and transitions to StateRunning. Returns an error if the server fails to start. Thread-safe; concurrent callers must serialize via singleflight in Manager.EnsureServerStarted.

func (*Server) State

func (s *Server) State() ServerState

State returns the current server state.

func (*Server) Stop

func (s *Server) Stop(ctx context.Context) error

Stop sends shutdown → exit, then kills the process after a timeout. Idempotent — safe to call on an already-stopped server.

type ServerState

type ServerState int

ServerState is the lifecycle state of one LSP server instance.

const (
	StateStopped ServerState = iota
	StateStarting
	StateRunning
	StateStopping
	StateError
)

func (ServerState) String

func (s ServerState) String() string

Directories

Path Synopsis
Package protocol holds hand-written LSP protocol types covering the subset of the LSP 3.17 spec needed by evva's Phase 1 operations (definition, references, hover, document symbols) plus the lifecycle handshake.
Package protocol holds hand-written LSP protocol types covering the subset of the LSP 3.17 spec needed by evva's Phase 1 operations (definition, references, hover, document symbols) plus the lifecycle handshake.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL