Documentation
¶
Overview ¶
Package lsp is live semantic code intelligence — definitions, references, types, hover, outline and diagnostics — over a repository AND its resolved dependencies, with no toolchain on the caller's machine.
Where it sits ¶
Under /v1/code, beside the static index. code and lsp are two reads of ONE repository, not two products: code is lexical, symbolic and semantic search — fast, approximate, always available — and lsp is a real language server — exact, typed, and able to follow a symbol out of the repository and into a dependency. An agent searches with code and is certain with lsp. One home, so there is one place to look for "what does this code mean".
What this package is ¶
A PROXY. The language servers run in hanzoai/lsp, a jailed daemon on its own deployment, because answering a cross-dependency question means running a third-party toolchain over untrusted bytes (see daemon.go). This side owns the three things the daemon must never hold: the tenant, the repository and the ledger.
- TENANT. Every request resolves its org from the validated principal, and that org is the daemon's isolation key. A caller supplies a repo SLUG, never an owner and never a URL, so there is no input from which one tenant could name another tenant's repository.
- REPOSITORY. The revision and the tree come from the git plane, over the socket, for the caller's own org. The daemon holds no git credential — one that could fetch any repository is exactly what must not exist next to an unjailed compiler — so the tree is pushed to it, never pulled by it.
- LEDGER. The gate runs before the work and the debit after it (meter.go).
Positions are the LSP's, not a translation of them ¶
line and character are 0-BASED, and character counts UTF-16 code units, per the LSP specification. That is deliberately not the 1-based line an editor shows a human: these callers are agents and editors that already speak LSP, and a service that silently re-based positions would corrupt every multi-byte line — an emoji before the cursor is one UTF-16 unit in the protocol's arithmetic and two in Go's. Positions pass through untouched, so the protocol's answer is the answer.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Answer ¶
type Answer struct {
Op string `json:"op"`
Lang string `json:"lang"`
Repo string `json:"repo"`
Rev string `json:"rev"`
Path string `json:"path"`
// Cold reports that this request paid to PREPARE the revision — the tree
// write, the dependency fetch and the language server's first index. It is
// the billed event, surfaced so a caller can see what it was charged for.
Cold bool `json:"cold"`
Locations []Location `json:"locations,omitempty"`
Hover string `json:"hover,omitempty"`
Symbols []Symbol `json:"symbols,omitempty"`
Completions []Completion `json:"completions,omitempty"`
Diagnostics []Diagnostic `json:"diagnostics,omitempty"`
}
Answer carries whichever result the op produces. Exactly one result field is populated, so a client reads the field its op names and never discriminates a union.
type Completion ¶
type Completion struct {
Label string `json:"label"`
Kind int `json:"kind,omitempty"`
Detail string `json:"detail,omitempty"`
}
Completion is one candidate at a position.
type Diagnostic ¶
type Diagnostic struct {
Range Range `json:"range"`
Severity int `json:"severity,omitempty"`
Code any `json:"code,omitempty"`
Source string `json:"source,omitempty"`
Message string `json:"message"`
}
Diagnostic is one problem the server reported. Severity is the LSP's: 1 error, 2 warning, 3 information, 4 hint.
type Location ¶
type Location struct {
Path string `json:"path"`
External bool `json:"external,omitempty"`
Range Range `json:"range"`
}
Location is one place an answer resolved to. External false means Path is repo-relative; true means the answer left the repository and Path is the module coordinate it landed in ("golang.org/x/mod@v0.14.0/semver/semver.go"), which is the whole reason this service exists.
type Query ¶
type Query struct {
// Repo is the repository NAME within the caller's own org, e.g. "cloud".
// Not a URL and not an owner/name pair: the owner is the validated
// principal's org, so this names a repository the caller already owns.
Repo string `json:"repo"`
// Rev is a branch, tag or commit sha. Empty means the default branch. It is
// resolved to a commit before anything else happens, so an answer is always
// about one immutable tree.
Rev string `json:"rev,omitempty"`
// Path is the repo-relative file, e.g. "apps/lsp/lsp.go".
Path string `json:"path"`
// Line is 0-based, per the LSP specification.
Line int `json:"line"`
// Character is a 0-based UTF-16 code-unit offset within Line, per the LSP
// specification — not a byte offset and not a rune index.
Character int `json:"character"`
// Relation refines locate: definition, reference, type or implementation.
// Empty means definition. Every other op ignores it.
Relation string `json:"relation,omitempty"`
}
Query is one position in one file of one repository — the value every op here takes, because every op here is one question about one position.