/** * Asking the language instead of grepping for it. * * "Where is this defined", "what calls this", "what type is this" are questions with exact answers, * and an agent that greps for them gets a list of places the name appears — comments, strings, a * different symbol with the same name in another module, and not the definition if it is re-exported. * Every wrong entry costs a file read, and the one that matters may not be in the list at all. * * Two providers, because there is no single one that is both correct and always present: * * - A real language server, if one is on PATH. Speaks LSP over stdio, works for whatever language * the server is for, and is the authority when it exists. * - The workspace's own TypeScript, otherwise. A TypeScript or JavaScript project being worked on * almost always has `typescript` in its node_modules, and its compiler API answers the same * questions with the same precision for those files. * * KONECK installs with `npm i -g koneck`, so neither is a dependency of KONECK. Requiring a global * language-server install would mean the feature was broken on the day most people first tried it, * and bundling a compiler for one language would put megabytes into every install to serve some of * them. What is present is used; what is absent is reported as absent, which is a usable answer. */ export type Lookup = 'definition' | 'references' | 'hover' | 'diagnostics'; export interface Position { line: number; character: number; } export interface Located { path: string; /** One-based, because that is what an editor and a person both count in. */ line: number; column: number; /** The line's text, so an answer is readable without another file read. */ text?: string; } export interface LookupResult { kind: Lookup; /** Which provider answered, so a thin answer can be judged. */ via: 'language-server' | 'typescript' | 'none'; found: Located[]; /** Type information, for hover. */ info?: string; /** Problems, for diagnostics. */ problems?: Array; /** Why there is no answer, when there is none. */ note?: string; } interface ServerSpec { /** The executable, looked for on PATH. */ command: string; args: string[]; extensions: string[]; language: string; } /** * Servers KONECK knows how to start, in the order they are preferred. * * Only ones that speak LSP over stdio and need no configuration file to do it: a server that must * be configured before it will answer is not something to start behind somebody's back. */ export declare const SERVERS: readonly ServerSpec[]; /** The server for a file, or nothing. */ export declare function serverFor(file: string, has?: (c: string) => boolean): ServerSpec | null; /** * The framing, which is the part that is easy to get subtly wrong. * * Every message is `Content-Length: N\r\n\r\n` then exactly N BYTES of JSON — bytes, not * characters. A header counted in characters truncates the first message containing anything * outside ASCII, which in practice means the first identifier with an accent in it. */ export declare function frame(message: unknown): Buffer; /** Pulls whole messages out of a growing buffer, leaving any partial one behind. */ export declare function unframe(buffer: Buffer): { messages: unknown[]; rest: Buffer; }; /** How long a server gets. Generous for a first request, which may include indexing. */ export declare const LSP_TIMEOUT_MS = 20000; /** Asks a real language server. Returns null when there is none, or it never answered. */ export declare function askServer(kind: Lookup, file: string, at: Position, root: string): Promise; /** The workspace's typescript, if it has one. Never KONECK's: this is about their code. */ export declare function workspaceTypeScript(root: string): typeof import('typescript') | null; /** Above this, a references query loads the file alone and says the answer may be partial. */ export declare const MAX_PROJECT_FILES = 3000; /** * Asks the compiler directly. * * The program is as small as the question allows: see programFiles. */ export declare function askTypeScript(kind: Lookup, file: string, at: Position, root: string): Promise; /** * Finds a symbol's position in a file by name, so a caller need not count characters. * * A tool call saying "where is `resolveEndpoint` defined" is what an agent can actually produce; * a line and character offset is what it would have to guess at. */ export declare function findSymbol(text: string, symbol: string): Position | null; /** * The answer, from whichever provider can give one. * * A real server first, because it is the authority for its language and knows about the whole * project. The compiler second, because it is nearly always there for the files it covers. Neither * being available is reported plainly — an agent told "no language support here" greps, which is * what it would have done anyway; an agent told nothing assumes an empty answer means no results. */ export declare function ask(kind: Lookup, file: string, symbolOrPosition: string | Position, root: string): Promise; export {}; //# sourceMappingURL=lsp.d.ts.map