@mrclrchtr/supi-lsp 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,353 +1,56 @@
1
- // LSP protocol types — minimal subset needed for our client.
2
- // Based on the Language Server Protocol specification.
3
- // biome-ignore-all lint/nursery/noExcessiveLinesPerFile: protocol types are intentionally centralized in one catalog file.
4
-
5
- // ── Positions & Ranges ────────────────────────────────────────────────
6
-
7
- /** 0-based line and character offset. */
8
- export interface Position {
9
- line: number;
10
- character: number;
11
- }
12
-
13
- export interface Range {
14
- start: Position;
15
- end: Position;
16
- }
17
-
18
- export interface Location {
19
- uri: string;
20
- range: Range;
21
- }
22
-
23
- export interface LocationLink {
24
- originSelectionRange?: Range;
25
- targetUri: string;
26
- targetRange: Range;
27
- targetSelectionRange: Range;
28
- }
29
-
30
- // ── Text Edits ────────────────────────────────────────────────────────
31
-
32
- export interface TextEdit {
33
- range: Range;
34
- newText: string;
35
- }
36
-
37
- export interface TextDocumentEdit {
38
- textDocument: { uri: string; version?: number | null };
39
- edits: TextEdit[];
40
- }
41
-
42
- export interface WorkspaceEdit {
43
- changes?: Record<string, TextEdit[]>;
44
- documentChanges?: TextDocumentEdit[];
45
- }
46
-
47
- // ── Diagnostics ───────────────────────────────────────────────────────
48
-
49
- export const DiagnosticSeverity = {
50
- Error: 1,
51
- Warning: 2,
52
- Information: 3,
53
- Hint: 4,
54
- } as const;
55
- export type DiagnosticSeverity = (typeof DiagnosticSeverity)[keyof typeof DiagnosticSeverity];
56
-
57
- export interface DiagnosticRelatedInformation {
58
- location: Location;
59
- message: string;
60
- }
61
-
62
- export interface Diagnostic {
63
- range: Range;
64
- severity?: DiagnosticSeverity;
65
- code?: number | string;
66
- codeDescription?: { href: string };
67
- source?: string;
68
- message: string;
69
- relatedInformation?: DiagnosticRelatedInformation[];
70
- }
71
-
72
- // ── Hover ─────────────────────────────────────────────────────────────
73
-
74
- export interface MarkupContent {
75
- kind: "plaintext" | "markdown";
76
- value: string;
77
- }
78
-
79
- export type MarkedString = string | { language: string; value: string };
80
-
81
- export interface Hover {
82
- contents: MarkupContent | MarkedString | MarkedString[];
83
- range?: Range;
84
- }
85
-
86
- // ── Symbols ───────────────────────────────────────────────────────────
87
-
88
- export const SymbolKind = {
89
- File: 1,
90
- Module: 2,
91
- Namespace: 3,
92
- Package: 4,
93
- Class: 5,
94
- Method: 6,
95
- Property: 7,
96
- Field: 8,
97
- Constructor: 9,
98
- Enum: 10,
99
- Interface: 11,
100
- Function: 12,
101
- Variable: 13,
102
- Constant: 14,
103
- String: 15,
104
- Number: 16,
105
- Boolean: 17,
106
- Array: 18,
107
- Object: 19,
108
- Key: 20,
109
- Null: 21,
110
- EnumMember: 22,
111
- Struct: 23,
112
- Event: 24,
113
- Operator: 25,
114
- TypeParameter: 26,
115
- } as const;
116
- export type SymbolKind = (typeof SymbolKind)[keyof typeof SymbolKind];
117
-
118
- export interface DocumentSymbol {
119
- name: string;
120
- detail?: string;
121
- kind: SymbolKind;
122
- range: Range;
123
- selectionRange: Range;
124
- children?: DocumentSymbol[];
125
- }
126
-
127
- export interface SymbolInformation {
128
- name: string;
129
- kind: SymbolKind;
130
- location: Location;
131
- containerName?: string;
132
- }
133
-
134
- export interface WorkspaceSymbol {
135
- name: string;
136
- kind: SymbolKind;
137
- location: Location;
138
- containerName?: string;
139
- /** LSP 3.17+ extra data for resolve support */
140
- data?: unknown;
141
- }
142
-
143
- // ── Code Actions ──────────────────────────────────────────────────────
144
-
145
- export interface CodeActionContext {
146
- diagnostics: Diagnostic[];
147
- only?: string[];
148
- }
149
-
150
- export interface Command {
151
- title: string;
152
- command: string;
153
- arguments?: unknown[];
154
- }
155
-
156
- export interface CodeAction {
157
- title: string;
158
- kind?: string;
159
- diagnostics?: Diagnostic[];
160
- isPreferred?: boolean;
161
- edit?: WorkspaceEdit;
162
- command?: Command;
163
- }
164
-
165
- // ── Publish Diagnostics ───────────────────────────────────────────────
166
-
167
- export interface PublishDiagnosticsParams {
168
- uri: string;
169
- version?: number;
170
- diagnostics: Diagnostic[];
171
- }
172
-
173
- export const FileChangeType = {
174
- Created: 1,
175
- Changed: 2,
176
- Deleted: 3,
177
- } as const;
178
- export type FileChangeType = (typeof FileChangeType)[keyof typeof FileChangeType];
179
-
180
- export interface FileEvent {
181
- uri: string;
182
- type: FileChangeType;
183
- }
184
-
185
- export interface DidChangeWatchedFilesParams {
186
- changes: FileEvent[];
187
- }
188
-
189
- // ── LSP 3.17 Pull Diagnostics ─────────────────────────────────────────
190
-
191
- export interface DocumentDiagnosticParams {
192
- textDocument: TextDocumentIdentifier;
193
- identifier?: string;
194
- previousResultId?: string;
195
- workDoneToken?: unknown;
196
- partialResultToken?: unknown;
197
- }
198
-
199
- /** LSP 3.17 document diagnostic report shape used by textDocument/diagnostic. */
200
- export type DocumentDiagnosticReport =
201
- | RelatedFullDocumentDiagnosticReport
202
- | RelatedUnchangedDocumentDiagnosticReport;
203
-
204
- /** Full document diagnostic report, optionally carrying related document reports. */
205
- export interface RelatedFullDocumentDiagnosticReport extends FullDocumentDiagnosticReport {
206
- relatedDocuments?: Record<
207
- string,
208
- FullDocumentDiagnosticReport | UnchangedDocumentDiagnosticReport
209
- >;
210
- }
211
-
212
- /** Unchanged document diagnostic report, optionally carrying related document reports. */
213
- export interface RelatedUnchangedDocumentDiagnosticReport
214
- extends UnchangedDocumentDiagnosticReport {
215
- relatedDocuments?: Record<
216
- string,
217
- FullDocumentDiagnosticReport | UnchangedDocumentDiagnosticReport
218
- >;
219
- }
220
-
221
- /** Full diagnostic payload for a document. */
222
- export interface FullDocumentDiagnosticReport {
223
- kind: "full";
224
- resultId?: string;
225
- items: Diagnostic[];
226
- }
227
-
228
- /** Result-id-only report indicating a document's diagnostics are unchanged. */
229
- export interface UnchangedDocumentDiagnosticReport {
230
- kind: "unchanged";
231
- resultId: string;
232
- }
233
-
234
- /** Client capability for pull diagnostics. */
235
- export interface ClientDiagnosticCapabilities {
236
- dynamicRegistration?: boolean;
237
- relatedDocumentSupport?: boolean;
238
- }
239
-
240
- // ── Initialize ────────────────────────────────────────────────────────
241
-
242
- export interface InitializeParams {
243
- processId: number | null;
244
- rootUri: string | null;
245
- capabilities: ClientCapabilities;
246
- initializationOptions?: unknown;
247
- }
248
-
249
- export interface ClientCapabilities {
250
- textDocument?: {
251
- synchronization?: {
252
- didSave?: boolean;
253
- dynamicRegistration?: boolean;
254
- };
255
- hover?: {
256
- contentFormat?: string[];
257
- dynamicRegistration?: boolean;
258
- };
259
- definition?: {
260
- dynamicRegistration?: boolean;
261
- linkSupport?: boolean;
262
- };
263
- references?: {
264
- dynamicRegistration?: boolean;
265
- };
266
- documentSymbol?: {
267
- dynamicRegistration?: boolean;
268
- hierarchicalDocumentSymbolSupport?: boolean;
269
- };
270
- rename?: {
271
- dynamicRegistration?: boolean;
272
- prepareSupport?: boolean;
273
- };
274
- codeAction?: {
275
- dynamicRegistration?: boolean;
276
- codeActionLiteralSupport?: {
277
- codeActionKind: { valueSet: string[] };
278
- };
279
- };
280
- publishDiagnostics?: {
281
- relatedInformation?: boolean;
282
- versionSupport?: boolean;
283
- };
284
- /** LSP 3.17+ pull diagnostic capability */
285
- diagnostic?: ClientDiagnosticCapabilities;
286
- };
287
- workspace?: {
288
- workspaceFolders?: boolean;
289
- diagnostics?: {
290
- refreshSupport?: boolean;
291
- };
292
- };
293
- }
294
-
295
- export interface InitializeResult {
296
- capabilities: ServerCapabilities;
297
- }
298
-
299
- export interface ServerCapabilities {
300
- textDocumentSync?: number | { openClose?: boolean; change?: number };
301
- hoverProvider?: boolean;
302
- definitionProvider?: boolean;
303
- referencesProvider?: boolean;
304
- documentSymbolProvider?: boolean;
305
- workspaceSymbolProvider?: boolean;
306
- renameProvider?: boolean | { prepareProvider?: boolean };
307
- codeActionProvider?: boolean | { codeActionKinds?: string[] };
308
- implementationProvider?: boolean;
309
- /** LSP 3.17+ pull diagnostic support */
310
- diagnosticProvider?:
311
- | boolean
312
- | {
313
- /** Document diagnostic provider */
314
- documentIdentifierProvider?: boolean | { workDoneProgress?: boolean };
315
- /** Workspace diagnostic provider */
316
- workspaceDiagnostics?: boolean | { workDoneProgress?: boolean };
317
- /** Identifier for result sets */
318
- identifierSet?: boolean;
319
- /** Inter-file dependency support */
320
- interFileDependencies?: boolean;
321
- /** Workspace-wide multi-file support */
322
- workspaceDiagnosticsSupport?: boolean;
323
- };
324
- }
325
-
326
- // ── Text Document Items ───────────────────────────────────────────────
327
-
328
- export interface TextDocumentIdentifier {
329
- uri: string;
330
- }
331
-
332
- export interface TextDocumentItem {
333
- uri: string;
334
- languageId: string;
335
- version: number;
336
- text: string;
337
- }
338
-
339
- export interface VersionedTextDocumentIdentifier {
340
- uri: string;
341
- version: number;
342
- }
343
-
344
- export interface TextDocumentPositionParams {
345
- textDocument: TextDocumentIdentifier;
346
- position: Position;
347
- }
348
-
349
- // ── JSON-RPC ──────────────────────────────────────────────────────────
350
-
1
+ // LSP protocol types — re-exported from vscode-languageserver-* packages.
2
+ // These are the canonical type definitions maintained by Microsoft alongside the LSP spec.
3
+
4
+ // ── Protocol types from vscode-languageserver-protocol ───────────────
5
+ export {
6
+ type ClientCapabilities,
7
+ DidChangeWatchedFilesParams,
8
+ DocumentDiagnosticParams,
9
+ type DocumentDiagnosticReport,
10
+ FileChangeType,
11
+ type FileEvent,
12
+ type FullDocumentDiagnosticReport,
13
+ type InitializeParams,
14
+ type InitializeResult,
15
+ PublishDiagnosticsParams,
16
+ type RelatedFullDocumentDiagnosticReport,
17
+ type RelatedUnchangedDocumentDiagnosticReport,
18
+ type ServerCapabilities,
19
+ TextDocumentPositionParams,
20
+ type UnchangedDocumentDiagnosticReport,
21
+ } from "vscode-languageserver-protocol";
22
+ // ── Core data types from vscode-languageserver-types ─────────────────
23
+ export {
24
+ CodeAction,
25
+ type CodeActionContext,
26
+ Command,
27
+ Diagnostic,
28
+ DiagnosticRelatedInformation,
29
+ DiagnosticSeverity,
30
+ DocumentSymbol,
31
+ Hover,
32
+ Location,
33
+ LocationLink,
34
+ MarkedString,
35
+ MarkupContent,
36
+ Position,
37
+ Range,
38
+ SymbolInformation,
39
+ SymbolKind,
40
+ TextDocumentEdit,
41
+ TextDocumentIdentifier,
42
+ TextDocumentItem,
43
+ TextEdit,
44
+ VersionedTextDocumentIdentifier,
45
+ WorkspaceEdit,
46
+ WorkspaceSymbol,
47
+ } from "vscode-languageserver-types";
48
+
49
+ // Alias for backward compatibility — our code uses ClientDiagnosticCapabilities
50
+ import type { DiagnosticClientCapabilities } from "vscode-languageserver-protocol";
51
+ export type ClientDiagnosticCapabilities = DiagnosticClientCapabilities;
52
+
53
+ // ── JSON-RPC types (local — replaced by vscode-jsonrpc in transport task) ──
351
54
  export type JsonRpcId = number | string;
352
55
 
353
56
  export interface JsonRpcRequest {
@@ -372,40 +75,11 @@ export interface JsonRpcNotification {
372
75
 
373
76
  export type JsonRpcMessage = JsonRpcRequest | JsonRpcResponse | JsonRpcNotification;
374
77
 
375
- // ── Server Configuration ──────────────────────────────────────────────
376
-
377
- export interface ServerConfig {
378
- command: string;
379
- args?: string[];
380
- fileTypes: string[];
381
- rootMarkers: string[];
382
- enabled?: boolean;
383
- initializationOptions?: unknown;
384
- }
385
-
386
- /** LSP configuration keyed by language name (e.g. `typescript`, `python`). */
387
- export interface LspConfig {
388
- servers: Record<string, ServerConfig>;
389
- }
390
-
391
- export interface DetectedProjectServer {
392
- name: string;
393
- root: string;
394
- fileTypes: string[];
395
- }
396
-
397
- export interface ProjectServerInfo extends DetectedProjectServer {
398
- status: "running" | "error" | "unavailable";
399
- supportedActions: string[];
400
- openFiles: string[];
401
- }
402
-
403
- /** A language whose source files are present but the server binary is missing. */
404
- export interface MissingServer {
405
- /** Language name (e.g. "python", "rust"). */
406
- name: string;
407
- /** Server command that was not found on PATH. */
408
- command: string;
409
- /** File extensions found in the project (subset of server.fileTypes). */
410
- foundExtensions: string[];
411
- }
78
+ // ── SuPi-specific server config ──────────────────────────────────────
79
+ export type {
80
+ DetectedProjectServer,
81
+ LspConfig,
82
+ MissingServer,
83
+ ProjectServerInfo,
84
+ ServerConfig,
85
+ } from "./server-config.ts";
package/src/format.ts CHANGED
@@ -11,6 +11,7 @@ import type {
11
11
  MarkupContent,
12
12
  SymbolInformation,
13
13
  WorkspaceEdit,
14
+ WorkspaceSymbol,
14
15
  } from "./config/types.ts";
15
16
  import { isProjectSource } from "./summary.ts";
16
17
  import { uriToFile } from "./utils.ts";
@@ -145,8 +146,8 @@ export function formatDocumentSymbols(symbols: DocumentSymbol[], indent: number)
145
146
  }
146
147
 
147
148
  export function formatSymbolInformation(symbols: SymbolInformation[], cwd: string): string {
148
- const projectSyms: SymbolInformation[] = [];
149
- const externalSyms: SymbolInformation[] = [];
149
+ const projectSyms: (SymbolInformation | WorkspaceSymbol)[] = [];
150
+ const externalSyms: (SymbolInformation | WorkspaceSymbol)[] = [];
150
151
  for (const sym of symbols) {
151
152
  if (isProjectSource(uriToFile(sym.location.uri), cwd)) {
152
153
  projectSyms.push(sym);
@@ -160,7 +161,7 @@ export function formatSymbolInformation(symbols: SymbolInformation[], cwd: strin
160
161
  for (const sym of symbolsToShow) {
161
162
  const kind = symbolKindName(sym.kind);
162
163
  const file = relPath(uriToFile(sym.location.uri), cwd);
163
- const line = sym.location.range.start.line + 1;
164
+ const line = "range" in sym.location ? sym.location.range.start.line + 1 : "?";
164
165
  const container = sym.containerName ? ` (in ${sym.containerName})` : "";
165
166
  lines.push(`- ${kind} **${sym.name}**${container} — ${file}:${line}`);
166
167
  }
@@ -183,6 +184,7 @@ interface EditEntry {
183
184
  edits: Array<{ range: { start: { line: number } }; newText: string }>;
184
185
  }
185
186
 
187
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: pre-existing — not introduced by this change
186
188
  function partitionWorkspaceEdit(
187
189
  edit: WorkspaceEdit,
188
190
  cwd: string,
@@ -203,6 +205,7 @@ function partitionWorkspaceEdit(
203
205
 
204
206
  if (edit.documentChanges) {
205
207
  for (const dc of edit.documentChanges) {
208
+ if (!("textDocument" in dc)) continue;
206
209
  const filePath = uriToFile(dc.textDocument.uri);
207
210
  if (isProjectSource(filePath, cwd)) {
208
211
  projectChanges.push({ file: relPath(filePath, cwd), edits: dc.edits });
@@ -258,11 +261,15 @@ export function formatCodeActions(actions: CodeAction[]): string {
258
261
 
259
262
  // ── Workspace Symbols ─────────────────────────────────────────────────
260
263
 
261
- export function formatWorkspaceSymbols(symbols: SymbolInformation[], cwd: string): string {
264
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: pre-existing threshold exceeded by widened parameter type for WorkspaceSymbol compatibility
265
+ export function formatWorkspaceSymbols(
266
+ symbols: (SymbolInformation | WorkspaceSymbol)[],
267
+ cwd: string,
268
+ ): string {
262
269
  if (symbols.length === 0) return "No symbols found.";
263
270
 
264
- const projectSyms: SymbolInformation[] = [];
265
- const externalSyms: SymbolInformation[] = [];
271
+ const projectSyms: (SymbolInformation | WorkspaceSymbol)[] = [];
272
+ const externalSyms: (SymbolInformation | WorkspaceSymbol)[] = [];
266
273
  for (const sym of symbols) {
267
274
  if (isProjectSource(uriToFile(sym.location.uri), cwd)) {
268
275
  projectSyms.push(sym);
@@ -279,8 +286,9 @@ export function formatWorkspaceSymbols(symbols: SymbolInformation[], cwd: string
279
286
  for (const sym of projectSyms) {
280
287
  const kind = symbolKindName(sym.kind);
281
288
  const file = relPath(uriToFile(sym.location.uri), cwd);
282
- const line = sym.location.range.start.line + 1;
283
- const col = sym.location.range.start.character + 1;
289
+ const loc = "range" in sym.location ? sym.location.range : null;
290
+ const line = loc ? loc.start.line + 1 : "?";
291
+ const col = loc ? loc.start.character + 1 : "?";
284
292
  const container = sym.containerName ? ` — ${sym.containerName}` : "";
285
293
  lines.push(`- **${sym.name}** (${kind})${container} — ${file}:${line}:${col}`);
286
294
  }
package/src/lsp.ts CHANGED
@@ -16,7 +16,7 @@ import type {
16
16
  import { pruneAndReorderContextMessages, restorePromptContent } from "@mrclrchtr/supi-core/api";
17
17
  import { loadConfig, resolveLanguageAlias } from "./config/config.ts";
18
18
  import { clearTsconfigCache } from "./config/tsconfig-scope.ts";
19
- import { FileChangeType } from "./config/types.ts";
19
+ import { FileChangeType, type FileEvent } from "./config/types.ts";
20
20
  import {
21
21
  diagnosticsContextFingerprint,
22
22
  formatDiagnosticsContext,
@@ -228,7 +228,7 @@ function recoverWorkspaceChangesFromToolResult(
228
228
  if (shouldInvalidateTsconfigScopeCache(resolvedPath)) {
229
229
  clearTsconfigCache();
230
230
  }
231
- const fileEvent = { uri: fileToUri(resolvedPath), type: FileChangeType.Changed };
231
+ const fileEvent: FileEvent = { uri: fileToUri(resolvedPath), type: FileChangeType.Changed };
232
232
 
233
233
  // Sentinel files (package.json, tsconfig.json, lockfiles, .d.ts)
234
234
  if (isWorkspaceRecoveryTrigger(resolvedPath, cwd)) {
@@ -1,5 +1,5 @@
1
1
  import type { LspClient } from "../client/client.ts";
2
- import type { ProjectServerInfo } from "../config/types.ts";
2
+ import type { ProjectServerInfo } from "../config/server-config.ts";
3
3
  import { displayRelativeFilePath } from "../summary.ts";
4
4
  import { getSupportedLspServerActions } from "../tool/tool-specs.ts";
5
5