@mastra/code-sdk 1.0.3-alpha.1 → 1.1.0-alpha.2

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.
Files changed (258) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/acp/agent.js +155 -167
  3. package/dist/acp/agent.js.map +1 -1
  4. package/dist/acp/event-mapper.js +193 -168
  5. package/dist/acp/event-mapper.js.map +1 -1
  6. package/dist/acp/index.js +60 -49
  7. package/dist/acp/index.js.map +1 -1
  8. package/dist/acp/server.js +31 -30
  9. package/dist/acp/server.js.map +1 -1
  10. package/dist/acp.js +1 -4
  11. package/dist/agents/credential-resolver.js +40 -29
  12. package/dist/agents/credential-resolver.js.map +1 -1
  13. package/dist/agents/custom-provider-source.js +16 -9
  14. package/dist/agents/custom-provider-source.js.map +1 -1
  15. package/dist/agents/instructions.js +27 -36
  16. package/dist/agents/instructions.js.map +1 -1
  17. package/dist/agents/mastracode-gateway.js +355 -428
  18. package/dist/agents/mastracode-gateway.js.map +1 -1
  19. package/dist/agents/memory.js +87 -78
  20. package/dist/agents/memory.js.map +1 -1
  21. package/dist/agents/model.js +114 -119
  22. package/dist/agents/model.js.map +1 -1
  23. package/dist/agents/modes/build.js +12 -13
  24. package/dist/agents/modes/build.js.map +1 -1
  25. package/dist/agents/modes/explore.js +14 -13
  26. package/dist/agents/modes/explore.js.map +1 -1
  27. package/dist/agents/modes/plan.js +14 -15
  28. package/dist/agents/modes/plan.js.map +1 -1
  29. package/dist/agents/prompts/agent-instructions.js +78 -69
  30. package/dist/agents/prompts/agent-instructions.js.map +1 -1
  31. package/dist/agents/prompts/build.js +19 -16
  32. package/dist/agents/prompts/build.js.map +1 -1
  33. package/dist/agents/prompts/fast.js +8 -4
  34. package/dist/agents/prompts/fast.js.map +1 -1
  35. package/dist/agents/prompts/index.js +48 -47
  36. package/dist/agents/prompts/index.js.map +1 -1
  37. package/dist/agents/prompts/model.js +6 -5
  38. package/dist/agents/prompts/model.js.map +1 -1
  39. package/dist/agents/prompts/plan.js +20 -16
  40. package/dist/agents/prompts/plan.js.map +1 -1
  41. package/dist/agents/prompts/tool-guidance.js +77 -109
  42. package/dist/agents/prompts/tool-guidance.js.map +1 -1
  43. package/dist/agents/sandbox-filesystem.js +245 -259
  44. package/dist/agents/sandbox-filesystem.js.map +1 -1
  45. package/dist/agents/sandbox-reattach.js +9 -11
  46. package/dist/agents/sandbox-reattach.js.map +1 -1
  47. package/dist/agents/thread-caveman-state.js +92 -81
  48. package/dist/agents/thread-caveman-state.js.map +1 -1
  49. package/dist/agents/tool-availability.js +62 -80
  50. package/dist/agents/tool-availability.js.map +1 -1
  51. package/dist/agents/tools.js +99 -139
  52. package/dist/agents/tools.js.map +1 -1
  53. package/dist/agents/workspace.js +232 -225
  54. package/dist/agents/workspace.js.map +1 -1
  55. package/dist/analytics.js +139 -128
  56. package/dist/analytics.js.map +1 -1
  57. package/dist/auth/authorization-input.js +39 -25
  58. package/dist/auth/authorization-input.js.map +1 -1
  59. package/dist/auth/device-code.js +112 -80
  60. package/dist/auth/device-code.js.map +1 -1
  61. package/dist/auth/index.js +2 -9
  62. package/dist/auth/pkce.js +27 -16
  63. package/dist/auth/pkce.js.map +1 -1
  64. package/dist/auth/providers/anthropic.js +107 -93
  65. package/dist/auth/providers/anthropic.js.map +1 -1
  66. package/dist/auth/providers/github-copilot.js +304 -293
  67. package/dist/auth/providers/github-copilot.js.map +1 -1
  68. package/dist/auth/providers/openai-codex.js +442 -460
  69. package/dist/auth/providers/openai-codex.js.map +1 -1
  70. package/dist/auth/providers/xai.js +179 -145
  71. package/dist/auth/providers/xai.js.map +1 -1
  72. package/dist/auth/storage.js +182 -175
  73. package/dist/auth/storage.js.map +1 -1
  74. package/dist/auth/types.js +1 -1
  75. package/dist/clipboard/index.js +206 -172
  76. package/dist/clipboard/index.js.map +1 -1
  77. package/dist/constants.js +11 -16
  78. package/dist/constants.js.map +1 -1
  79. package/dist/error-classification.js +19 -11
  80. package/dist/error-classification.js.map +1 -1
  81. package/dist/evals/context-builder.js +145 -104
  82. package/dist/evals/context-builder.js.map +1 -1
  83. package/dist/evals/index.js +4 -7
  84. package/dist/evals/scorers/classify-command.js +62 -41
  85. package/dist/evals/scorers/classify-command.js.map +1 -1
  86. package/dist/evals/scorers/efficiency.js +239 -181
  87. package/dist/evals/scorers/efficiency.js.map +1 -1
  88. package/dist/evals/scorers/extract-tools.js +51 -47
  89. package/dist/evals/scorers/extract-tools.js.map +1 -1
  90. package/dist/evals/scorers/index.js +1 -5
  91. package/dist/evals/scorers/outcome.js +321 -212
  92. package/dist/evals/scorers/outcome.js.map +1 -1
  93. package/dist/goal-manager.js +266 -261
  94. package/dist/goal-manager.js.map +1 -1
  95. package/dist/goal-signal.js +14 -13
  96. package/dist/goal-signal.js.map +1 -1
  97. package/dist/headless/cli.js +153 -154
  98. package/dist/headless/cli.js.map +1 -1
  99. package/dist/headless/flags.js +180 -178
  100. package/dist/headless/flags.js.map +1 -1
  101. package/dist/headless/format.js +72 -71
  102. package/dist/headless/format.js.map +1 -1
  103. package/dist/headless/index.js +5 -31
  104. package/dist/headless/policy.js +35 -31
  105. package/dist/headless/policy.js.map +1 -1
  106. package/dist/headless/run-mc.js +332 -334
  107. package/dist/headless/run-mc.js.map +1 -1
  108. package/dist/headless/types.js +16 -7
  109. package/dist/headless/types.js.map +1 -1
  110. package/dist/hooks/config.js +56 -61
  111. package/dist/hooks/config.js.map +1 -1
  112. package/dist/hooks/executor.js +118 -116
  113. package/dist/hooks/executor.js.map +1 -1
  114. package/dist/hooks/index.js +4 -15
  115. package/dist/hooks/manager.js +221 -280
  116. package/dist/hooks/manager.js.map +1 -1
  117. package/dist/hooks/types.js +5 -4
  118. package/dist/hooks/types.js.map +1 -1
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +632 -712
  121. package/dist/index.js.map +1 -1
  122. package/dist/ipc/ipc-reporter.js +19 -22
  123. package/dist/ipc/ipc-reporter.js.map +1 -1
  124. package/dist/lsp/client.js +248 -306
  125. package/dist/lsp/client.js.map +1 -1
  126. package/dist/lsp/index.js +1 -6
  127. package/dist/lsp/language.js +39 -43
  128. package/dist/lsp/language.js.map +1 -1
  129. package/dist/lsp/manager.js +78 -93
  130. package/dist/lsp/manager.js.map +1 -1
  131. package/dist/lsp/server.js +151 -120
  132. package/dist/lsp/server.js.map +1 -1
  133. package/dist/lsp/workspace.js +50 -47
  134. package/dist/lsp/workspace.js.map +1 -1
  135. package/dist/mcp/config.js +210 -199
  136. package/dist/mcp/config.js.map +1 -1
  137. package/dist/mcp/index.js +2 -9
  138. package/dist/mcp/manager.js +482 -475
  139. package/dist/mcp/manager.js.map +1 -1
  140. package/dist/mcp/types.js +1 -1
  141. package/dist/onboarding/custom-packs.js +14 -17
  142. package/dist/onboarding/custom-packs.js.map +1 -1
  143. package/dist/onboarding/custom-providers.js +22 -20
  144. package/dist/onboarding/custom-providers.js.map +1 -1
  145. package/dist/onboarding/index.d.ts +1 -1
  146. package/dist/onboarding/index.d.ts.map +1 -1
  147. package/dist/onboarding/index.js +3 -21
  148. package/dist/onboarding/om-settings.d.ts +5 -0
  149. package/dist/onboarding/om-settings.d.ts.map +1 -1
  150. package/dist/onboarding/om-settings.js +41 -20
  151. package/dist/onboarding/om-settings.js.map +1 -1
  152. package/dist/onboarding/packs.d.ts +4 -6
  153. package/dist/onboarding/packs.d.ts.map +1 -1
  154. package/dist/onboarding/packs.js +154 -105
  155. package/dist/onboarding/packs.js.map +1 -1
  156. package/dist/onboarding/settings.js +575 -517
  157. package/dist/onboarding/settings.js.map +1 -1
  158. package/dist/permissions.js +112 -99
  159. package/dist/permissions.js.map +1 -1
  160. package/dist/plugin.js +21 -23
  161. package/dist/plugin.js.map +1 -1
  162. package/dist/plugins/dependencies.js +64 -87
  163. package/dist/plugins/dependencies.js.map +1 -1
  164. package/dist/plugins/install.js +159 -169
  165. package/dist/plugins/install.js.map +1 -1
  166. package/dist/plugins/loader.js +170 -185
  167. package/dist/plugins/loader.js.map +1 -1
  168. package/dist/plugins/manager.js +374 -380
  169. package/dist/plugins/manager.js.map +1 -1
  170. package/dist/plugins/manifest.js +38 -63
  171. package/dist/plugins/manifest.js.map +1 -1
  172. package/dist/plugins/package-link.js +48 -64
  173. package/dist/plugins/package-link.js.map +1 -1
  174. package/dist/plugins/paths.js +18 -19
  175. package/dist/plugins/paths.js.map +1 -1
  176. package/dist/plugins/registry.js +97 -81
  177. package/dist/plugins/registry.js.map +1 -1
  178. package/dist/plugins/scaffold.js +62 -98
  179. package/dist/plugins/scaffold.js.map +1 -1
  180. package/dist/plugins/types.js +1 -1
  181. package/dist/processors/plan-rejection-abort.js +45 -44
  182. package/dist/processors/plan-rejection-abort.js.map +1 -1
  183. package/dist/providers/amazon-bedrock-gateway.js +134 -125
  184. package/dist/providers/amazon-bedrock-gateway.js.map +1 -1
  185. package/dist/providers/amazon-bedrock.js +68 -47
  186. package/dist/providers/amazon-bedrock.js.map +1 -1
  187. package/dist/providers/claude-max.js +153 -133
  188. package/dist/providers/claude-max.js.map +1 -1
  189. package/dist/providers/github-copilot.js +232 -230
  190. package/dist/providers/github-copilot.js.map +1 -1
  191. package/dist/providers/openai-codex.js +271 -260
  192. package/dist/providers/openai-codex.js.map +1 -1
  193. package/dist/providers/xai.js +57 -50
  194. package/dist/providers/xai.js.map +1 -1
  195. package/dist/schema.js +91 -89
  196. package/dist/schema.js.map +1 -1
  197. package/dist/theme-palette.js +18 -14
  198. package/dist/theme-palette.js.map +1 -1
  199. package/dist/tool-names.js +46 -37
  200. package/dist/tool-names.js.map +1 -1
  201. package/dist/tools/index.js +2 -8
  202. package/dist/tools/request-sandbox-access.js +71 -80
  203. package/dist/tools/request-sandbox-access.js.map +1 -1
  204. package/dist/tools/utils.js +26 -16
  205. package/dist/tools/utils.js.map +1 -1
  206. package/dist/tools/web-search.js +51 -55
  207. package/dist/tools/web-search.js.map +1 -1
  208. package/dist/utils/binaries.js +65 -61
  209. package/dist/utils/binaries.js.map +1 -1
  210. package/dist/utils/debug-log.js +51 -47
  211. package/dist/utils/debug-log.js.map +1 -1
  212. package/dist/utils/errors.js +157 -192
  213. package/dist/utils/errors.js.map +1 -1
  214. package/dist/utils/gateway-sync.js +49 -37
  215. package/dist/utils/gateway-sync.js.map +1 -1
  216. package/dist/utils/path-security.js +7 -6
  217. package/dist/utils/path-security.js.map +1 -1
  218. package/dist/utils/plan-diff.js +58 -39
  219. package/dist/utils/plan-diff.js.map +1 -1
  220. package/dist/utils/plans.js +92 -74
  221. package/dist/utils/plans.js.map +1 -1
  222. package/dist/utils/project.js +318 -256
  223. package/dist/utils/project.js.map +1 -1
  224. package/dist/utils/signals-pubsub.js +117 -99
  225. package/dist/utils/signals-pubsub.js.map +1 -1
  226. package/dist/utils/slash-command-loader.js +118 -154
  227. package/dist/utils/slash-command-loader.js.map +1 -1
  228. package/dist/utils/slash-command-processor.js +92 -83
  229. package/dist/utils/slash-command-processor.js.map +1 -1
  230. package/dist/utils/stdin-pipe.js +87 -63
  231. package/dist/utils/stdin-pipe.js.map +1 -1
  232. package/dist/utils/storage-factory.js +104 -84
  233. package/dist/utils/storage-factory.js.map +1 -1
  234. package/dist/utils/storage-maintenance.js +249 -211
  235. package/dist/utils/storage-maintenance.js.map +1 -1
  236. package/dist/utils/thread-lock.js +96 -92
  237. package/dist/utils/thread-lock.js.map +1 -1
  238. package/dist/utils/token-estimator.js +12 -12
  239. package/dist/utils/token-estimator.js.map +1 -1
  240. package/dist/utils/update-check.d.ts +1 -1
  241. package/dist/utils/update-check.js +341 -259
  242. package/dist/utils/update-check.js.map +1 -1
  243. package/dist/voice/stt-registry.js +131 -113
  244. package/dist/voice/stt-registry.js.map +1 -1
  245. package/package.json +12 -12
  246. package/dist/acp.js.map +0 -1
  247. package/dist/auth/index.js.map +0 -1
  248. package/dist/auth/types.js.map +0 -1
  249. package/dist/evals/index.js.map +0 -1
  250. package/dist/evals/scorers/index.js.map +0 -1
  251. package/dist/headless/index.js.map +0 -1
  252. package/dist/hooks/index.js.map +0 -1
  253. package/dist/lsp/index.js.map +0 -1
  254. package/dist/mcp/index.js.map +0 -1
  255. package/dist/mcp/types.js.map +0 -1
  256. package/dist/onboarding/index.js.map +0 -1
  257. package/dist/plugins/types.js.map +0 -1
  258. package/dist/tools/index.js.map +0 -1
@@ -1,309 +1,251 @@
1
1
  import { StreamMessageReader, StreamMessageWriter, createMessageConnection } from "vscode-jsonrpc/node.js";
2
- import { TextDocumentIdentifier, Position } from "vscode-languageserver-protocol";
3
- class LSPClient {
4
- connection = null;
5
- process = null;
6
- serverInfo;
7
- workspaceRoot;
8
- diagnostics = /* @__PURE__ */ new Map();
9
- initializationOptions = null;
10
- constructor(serverInfo, workspaceRoot) {
11
- this.serverInfo = serverInfo;
12
- this.workspaceRoot = workspaceRoot;
13
- }
14
- /**
15
- * Initialize the LSP connection
16
- */
17
- async initialize() {
18
- const spawnResult = await this.serverInfo.spawn(this.workspaceRoot);
19
- if (!spawnResult) {
20
- throw new Error("Failed to spawn LSP server");
21
- }
22
- let initializationOptions = void 0;
23
- if ("process" in spawnResult) {
24
- this.process = spawnResult.process;
25
- initializationOptions = spawnResult.initialization;
26
- } else {
27
- this.process = spawnResult;
28
- }
29
- if (!this.process.stdin || !this.process.stdout) {
30
- throw new Error("Failed to create LSP process with proper stdio");
31
- }
32
- const reader = new StreamMessageReader(this.process.stdout);
33
- const writer = new StreamMessageWriter(this.process.stdin);
34
- this.connection = createMessageConnection(reader, writer);
35
- this.connection.onError((error) => {
36
- const errorObj = error?.[0];
37
- if (errorObj?.code !== "ERR_STREAM_DESTROYED") {
38
- }
39
- });
40
- this.connection.onNotification("textDocument/publishDiagnostics", (params) => {
41
- if (params.diagnostics && params.diagnostics.length > 0) {
42
- }
43
- this.diagnostics.set(params.uri, params.diagnostics);
44
- });
45
- this.connection.onNotification((_method, _params) => {
46
- });
47
- this.connection.listen();
48
- if (this.process.stderr) {
49
- this.process.stderr.on("data", (_data) => {
50
- });
51
- }
52
- this.process.on("error", (_error) => {
53
- });
54
- this.process.on("exit", (_code, _signal) => {
55
- });
56
- const initParams = {
57
- processId: process.pid,
58
- rootUri: `file://${this.workspaceRoot}`,
59
- workspaceFolders: [
60
- {
61
- name: "workspace",
62
- uri: `file://${this.workspaceRoot}`
63
- }
64
- ],
65
- capabilities: {
66
- window: {
67
- workDoneProgress: true
68
- },
69
- workspace: {
70
- configuration: true
71
- },
72
- textDocument: {
73
- publishDiagnostics: {
74
- relatedInformation: true,
75
- tagSupport: {
76
- valueSet: [1, 2]
77
- },
78
- versionSupport: false
79
- },
80
- synchronization: {
81
- didOpen: true,
82
- didChange: true,
83
- dynamicRegistration: false,
84
- willSave: false,
85
- willSaveWaitUntil: false,
86
- didSave: false
87
- },
88
- completion: {
89
- dynamicRegistration: false,
90
- completionItem: {
91
- snippetSupport: false,
92
- commitCharactersSupport: false,
93
- documentationFormat: ["markdown", "plaintext"],
94
- deprecatedSupport: false,
95
- preselectSupport: false
96
- }
97
- },
98
- definition: {
99
- dynamicRegistration: false,
100
- linkSupport: true
101
- },
102
- typeDefinition: {
103
- dynamicRegistration: false,
104
- linkSupport: true
105
- },
106
- implementation: {
107
- dynamicRegistration: false,
108
- linkSupport: true
109
- },
110
- references: {
111
- dynamicRegistration: false
112
- },
113
- documentHighlight: {
114
- dynamicRegistration: false
115
- },
116
- documentSymbol: {
117
- dynamicRegistration: false,
118
- hierarchicalDocumentSymbolSupport: true
119
- },
120
- codeAction: {
121
- dynamicRegistration: false,
122
- codeActionLiteralSupport: {
123
- codeActionKind: {
124
- valueSet: [
125
- "quickfix",
126
- "refactor",
127
- "refactor.extract",
128
- "refactor.inline",
129
- "refactor.rewrite",
130
- "source",
131
- "source.organizeImports"
132
- ]
133
- }
134
- }
135
- },
136
- hover: {
137
- dynamicRegistration: false,
138
- contentFormat: ["markdown", "plaintext"]
139
- }
140
- }
141
- }
142
- };
143
- if (initializationOptions) {
144
- initParams.initializationOptions = initializationOptions;
145
- this.initializationOptions = initializationOptions;
146
- }
147
- this.connection.onRequest("workspace/configuration", (params) => {
148
- return params.items?.map(() => ({})) || [];
149
- });
150
- this.connection.onRequest("window/workDoneProgress/create", (_params) => {
151
- return null;
152
- });
153
- await Promise.race([
154
- this.connection.sendRequest("initialize", initParams),
155
- new Promise((_, reject) => setTimeout(() => reject(new Error("LSP initialize request timed out")), 1e4))
156
- ]);
157
- this.connection.sendNotification("initialized", {});
158
- if (this.initializationOptions) {
159
- this.connection.sendNotification("workspace/didChangeConfiguration", {
160
- settings: this.initializationOptions
161
- });
162
- } else {
163
- this.connection.sendNotification("workspace/didChangeConfiguration", {
164
- settings: {}
165
- });
166
- }
167
- }
168
- /**
169
- * Notify the server that a document has been opened
170
- */
171
- notifyOpen(filePath, content, languageId) {
172
- if (!this.connection) return;
173
- const uri = `file://${filePath}`;
174
- this.diagnostics.delete(uri);
175
- this.connection.sendNotification("textDocument/didOpen", {
176
- textDocument: {
177
- uri,
178
- languageId,
179
- version: 0,
180
- text: content
181
- }
182
- });
183
- }
184
- /**
185
- * Notify the server that a document has changed
186
- */
187
- notifyChange(filePath, content, version) {
188
- if (!this.connection) return;
189
- this.connection.sendNotification("textDocument/didChange", {
190
- textDocument: {
191
- uri: `file://${filePath}`,
192
- version
193
- },
194
- contentChanges: [{ text: content }]
195
- });
196
- }
197
- /**
198
- * Wait for diagnostics to be available for a specific file
199
- * @param waitForChange If true, waits for diagnostics to change from their initial state
200
- */
201
- async waitForDiagnostics(filePath, timeoutMs = 5e3, waitForChange = false) {
202
- if (!this.connection) return [];
203
- const uri = `file://${filePath}`;
204
- const startTime = Date.now();
205
- const initialDiagnostics = this.diagnostics.get(uri);
206
- const initialCount = initialDiagnostics?.length || 0;
207
- while (Date.now() - startTime < timeoutMs) {
208
- const currentDiagnostics = this.diagnostics.get(uri);
209
- const currentCount = currentDiagnostics?.length || 0;
210
- if (waitForChange) {
211
- if (currentDiagnostics !== void 0 && currentCount !== initialCount) {
212
- return currentDiagnostics;
213
- }
214
- } else {
215
- if (currentDiagnostics !== void 0) {
216
- return currentDiagnostics;
217
- }
218
- }
219
- await new Promise((resolve) => setTimeout(resolve, 100));
220
- }
221
- return waitForChange ? initialDiagnostics || [] : [];
222
- }
223
- /**
224
- * Get hover information for a position
225
- */
226
- async getHover(filePath, line, character) {
227
- if (!this.connection) return null;
228
- try {
229
- return await this.connection.sendRequest("textDocument/hover", {
230
- textDocument: TextDocumentIdentifier.create(`file://${filePath}`),
231
- position: Position.create(line, character)
232
- });
233
- } catch {
234
- return null;
235
- }
236
- }
237
- /**
238
- * Get diagnostics for a specific file
239
- */
240
- getDiagnostics(filePath) {
241
- const uri = `file://${filePath}`;
242
- return this.diagnostics.get(uri) || [];
243
- }
244
- /**
245
- * Get all diagnostics from all files
246
- */
247
- getAllDiagnostics() {
248
- const allDiagnostics = [];
249
- for (const diagnostics of this.diagnostics.values()) {
250
- allDiagnostics.push(...diagnostics);
251
- }
252
- return allDiagnostics;
253
- }
254
- /**
255
- * Notify server that a file was closed
256
- */
257
- notifyClose(filePath) {
258
- if (!this.connection) return;
259
- const uri = `file://${filePath}`;
260
- this.diagnostics.delete(uri);
261
- this.connection.sendNotification("textDocument/didClose", {
262
- textDocument: TextDocumentIdentifier.create(uri)
263
- });
264
- }
265
- /**
266
- * Restart the LSP client
267
- */
268
- async restart() {
269
- await this.shutdown();
270
- await this.initialize();
271
- }
272
- /**
273
- * Shutdown the connection
274
- */
275
- async shutdown() {
276
- if (this.connection) {
277
- try {
278
- const processAlive = this.process && !this.process.killed;
279
- if (processAlive) {
280
- await Promise.race([
281
- this.connection.sendRequest("shutdown"),
282
- new Promise((_, reject) => setTimeout(() => reject(new Error("Shutdown request timed out")), 1e3))
283
- ]);
284
- this.connection.sendNotification("exit");
285
- }
286
- } catch {
287
- }
288
- try {
289
- this.connection.dispose();
290
- } catch {
291
- }
292
- this.connection = null;
293
- }
294
- if (this.process) {
295
- try {
296
- if (!this.process.killed) {
297
- this.process.kill();
298
- }
299
- } catch {
300
- }
301
- this.process = null;
302
- }
303
- this.diagnostics = /* @__PURE__ */ new Map();
304
- }
305
- }
306
- export {
307
- LSPClient
2
+ import { Position, TextDocumentIdentifier } from "vscode-languageserver-protocol";
3
+ //#region src/lsp/client.ts
4
+ /**
5
+ * LSP Client wrapper for JSON-RPC communication
6
+ */
7
+ var LSPClient = class {
8
+ connection = null;
9
+ process = null;
10
+ serverInfo;
11
+ workspaceRoot;
12
+ diagnostics = /* @__PURE__ */ new Map();
13
+ initializationOptions = null;
14
+ constructor(serverInfo, workspaceRoot) {
15
+ this.serverInfo = serverInfo;
16
+ this.workspaceRoot = workspaceRoot;
17
+ }
18
+ /**
19
+ * Initialize the LSP connection
20
+ */
21
+ async initialize() {
22
+ const spawnResult = await this.serverInfo.spawn(this.workspaceRoot);
23
+ if (!spawnResult) throw new Error("Failed to spawn LSP server");
24
+ let initializationOptions = void 0;
25
+ if ("process" in spawnResult) {
26
+ this.process = spawnResult.process;
27
+ initializationOptions = spawnResult.initialization;
28
+ } else this.process = spawnResult;
29
+ if (!this.process.stdin || !this.process.stdout) throw new Error("Failed to create LSP process with proper stdio");
30
+ const reader = new StreamMessageReader(this.process.stdout);
31
+ const writer = new StreamMessageWriter(this.process.stdin);
32
+ this.connection = createMessageConnection(reader, writer);
33
+ this.connection.onError((error) => {
34
+ if ((error?.[0])?.code !== "ERR_STREAM_DESTROYED") {}
35
+ });
36
+ this.connection.onNotification("textDocument/publishDiagnostics", (params) => {
37
+ if (params.diagnostics && params.diagnostics.length > 0) {}
38
+ this.diagnostics.set(params.uri, params.diagnostics);
39
+ });
40
+ this.connection.onNotification((_method, _params) => {});
41
+ this.connection.listen();
42
+ if (this.process.stderr) this.process.stderr.on("data", (_data) => {});
43
+ this.process.on("error", (_error) => {});
44
+ this.process.on("exit", (_code, _signal) => {});
45
+ const initParams = {
46
+ processId: process.pid,
47
+ rootUri: `file://${this.workspaceRoot}`,
48
+ workspaceFolders: [{
49
+ name: "workspace",
50
+ uri: `file://${this.workspaceRoot}`
51
+ }],
52
+ capabilities: {
53
+ window: { workDoneProgress: true },
54
+ workspace: { configuration: true },
55
+ textDocument: {
56
+ publishDiagnostics: {
57
+ relatedInformation: true,
58
+ tagSupport: { valueSet: [1, 2] },
59
+ versionSupport: false
60
+ },
61
+ synchronization: {
62
+ didOpen: true,
63
+ didChange: true,
64
+ dynamicRegistration: false,
65
+ willSave: false,
66
+ willSaveWaitUntil: false,
67
+ didSave: false
68
+ },
69
+ completion: {
70
+ dynamicRegistration: false,
71
+ completionItem: {
72
+ snippetSupport: false,
73
+ commitCharactersSupport: false,
74
+ documentationFormat: ["markdown", "plaintext"],
75
+ deprecatedSupport: false,
76
+ preselectSupport: false
77
+ }
78
+ },
79
+ definition: {
80
+ dynamicRegistration: false,
81
+ linkSupport: true
82
+ },
83
+ typeDefinition: {
84
+ dynamicRegistration: false,
85
+ linkSupport: true
86
+ },
87
+ implementation: {
88
+ dynamicRegistration: false,
89
+ linkSupport: true
90
+ },
91
+ references: { dynamicRegistration: false },
92
+ documentHighlight: { dynamicRegistration: false },
93
+ documentSymbol: {
94
+ dynamicRegistration: false,
95
+ hierarchicalDocumentSymbolSupport: true
96
+ },
97
+ codeAction: {
98
+ dynamicRegistration: false,
99
+ codeActionLiteralSupport: { codeActionKind: { valueSet: [
100
+ "quickfix",
101
+ "refactor",
102
+ "refactor.extract",
103
+ "refactor.inline",
104
+ "refactor.rewrite",
105
+ "source",
106
+ "source.organizeImports"
107
+ ] } }
108
+ },
109
+ hover: {
110
+ dynamicRegistration: false,
111
+ contentFormat: ["markdown", "plaintext"]
112
+ }
113
+ }
114
+ }
115
+ };
116
+ if (initializationOptions) {
117
+ initParams.initializationOptions = initializationOptions;
118
+ this.initializationOptions = initializationOptions;
119
+ }
120
+ this.connection.onRequest("workspace/configuration", (params) => {
121
+ return params.items?.map(() => ({})) || [];
122
+ });
123
+ this.connection.onRequest("window/workDoneProgress/create", (_params) => {
124
+ return null;
125
+ });
126
+ await Promise.race([this.connection.sendRequest("initialize", initParams), new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error("LSP initialize request timed out")), 1e4))]);
127
+ this.connection.sendNotification("initialized", {});
128
+ if (this.initializationOptions) this.connection.sendNotification("workspace/didChangeConfiguration", { settings: this.initializationOptions });
129
+ else this.connection.sendNotification("workspace/didChangeConfiguration", { settings: {} });
130
+ }
131
+ /**
132
+ * Notify the server that a document has been opened
133
+ */
134
+ notifyOpen(filePath, content, languageId) {
135
+ if (!this.connection) return;
136
+ const uri = `file://${filePath}`;
137
+ this.diagnostics.delete(uri);
138
+ this.connection.sendNotification("textDocument/didOpen", { textDocument: {
139
+ uri,
140
+ languageId,
141
+ version: 0,
142
+ text: content
143
+ } });
144
+ }
145
+ /**
146
+ * Notify the server that a document has changed
147
+ */
148
+ notifyChange(filePath, content, version) {
149
+ if (!this.connection) return;
150
+ this.connection.sendNotification("textDocument/didChange", {
151
+ textDocument: {
152
+ uri: `file://${filePath}`,
153
+ version
154
+ },
155
+ contentChanges: [{ text: content }]
156
+ });
157
+ }
158
+ /**
159
+ * Wait for diagnostics to be available for a specific file
160
+ * @param waitForChange If true, waits for diagnostics to change from their initial state
161
+ */
162
+ async waitForDiagnostics(filePath, timeoutMs = 5e3, waitForChange = false) {
163
+ if (!this.connection) return [];
164
+ const uri = `file://${filePath}`;
165
+ const startTime = Date.now();
166
+ const initialDiagnostics = this.diagnostics.get(uri);
167
+ const initialCount = initialDiagnostics?.length || 0;
168
+ while (Date.now() - startTime < timeoutMs) {
169
+ const currentDiagnostics = this.diagnostics.get(uri);
170
+ const currentCount = currentDiagnostics?.length || 0;
171
+ if (waitForChange) {
172
+ if (currentDiagnostics !== void 0 && currentCount !== initialCount) return currentDiagnostics;
173
+ } else if (currentDiagnostics !== void 0) return currentDiagnostics;
174
+ await new Promise((resolve) => setTimeout(resolve, 100));
175
+ }
176
+ return waitForChange ? initialDiagnostics || [] : [];
177
+ }
178
+ /**
179
+ * Get hover information for a position
180
+ */
181
+ async getHover(filePath, line, character) {
182
+ if (!this.connection) return null;
183
+ try {
184
+ return await this.connection.sendRequest("textDocument/hover", {
185
+ textDocument: TextDocumentIdentifier.create(`file://${filePath}`),
186
+ position: Position.create(line, character)
187
+ });
188
+ } catch {
189
+ return null;
190
+ }
191
+ }
192
+ /**
193
+ * Get diagnostics for a specific file
194
+ */
195
+ getDiagnostics(filePath) {
196
+ const uri = `file://${filePath}`;
197
+ return this.diagnostics.get(uri) || [];
198
+ }
199
+ /**
200
+ * Get all diagnostics from all files
201
+ */
202
+ getAllDiagnostics() {
203
+ const allDiagnostics = [];
204
+ for (const diagnostics of this.diagnostics.values()) allDiagnostics.push(...diagnostics);
205
+ return allDiagnostics;
206
+ }
207
+ /**
208
+ * Notify server that a file was closed
209
+ */
210
+ notifyClose(filePath) {
211
+ if (!this.connection) return;
212
+ const uri = `file://${filePath}`;
213
+ this.diagnostics.delete(uri);
214
+ this.connection.sendNotification("textDocument/didClose", { textDocument: TextDocumentIdentifier.create(uri) });
215
+ }
216
+ /**
217
+ * Restart the LSP client
218
+ */
219
+ async restart() {
220
+ await this.shutdown();
221
+ await this.initialize();
222
+ }
223
+ /**
224
+ * Shutdown the connection
225
+ */
226
+ async shutdown() {
227
+ if (this.connection) {
228
+ try {
229
+ if (this.process && !this.process.killed) {
230
+ await Promise.race([this.connection.sendRequest("shutdown"), new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error("Shutdown request timed out")), 1e3))]);
231
+ this.connection.sendNotification("exit");
232
+ }
233
+ } catch {}
234
+ try {
235
+ this.connection.dispose();
236
+ } catch {}
237
+ this.connection = null;
238
+ }
239
+ if (this.process) {
240
+ try {
241
+ if (!this.process.killed) this.process.kill();
242
+ } catch {}
243
+ this.process = null;
244
+ }
245
+ this.diagnostics = /* @__PURE__ */ new Map();
246
+ }
308
247
  };
248
+ //#endregion
249
+ export { LSPClient };
250
+
309
251
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lsp/client.ts"],"sourcesContent":["import type { ChildProcess } from 'node:child_process';\nimport { StreamMessageReader, StreamMessageWriter, createMessageConnection } from 'vscode-jsonrpc/node.js';\nimport type { MessageConnection } from 'vscode-jsonrpc/node.js';\nimport { TextDocumentIdentifier, Position } from 'vscode-languageserver-protocol';\nimport type { Diagnostic } from 'vscode-languageserver-protocol';\nimport type { LSPServerInfo } from './server.js';\n\n/**\n * LSP Client wrapper for JSON-RPC communication\n */\nexport class LSPClient {\n private connection: MessageConnection | null = null;\n private process: ChildProcess | null = null;\n private serverInfo: LSPServerInfo;\n private workspaceRoot: string;\n private diagnostics: Map<string, Diagnostic[]> = new Map();\n private initializationOptions: any = null;\n\n constructor(serverInfo: LSPServerInfo, workspaceRoot: string) {\n this.serverInfo = serverInfo;\n this.workspaceRoot = workspaceRoot;\n }\n\n /**\n * Initialize the LSP connection\n */\n async initialize(): Promise<void> {\n const spawnResult = await this.serverInfo.spawn(this.workspaceRoot);\n\n if (!spawnResult) {\n throw new Error('Failed to spawn LSP server');\n }\n\n // Handle both ChildProcess and { process: ChildProcess, initialization? } formats\n let initializationOptions: any = undefined;\n if ('process' in spawnResult) {\n this.process = spawnResult.process;\n initializationOptions = spawnResult.initialization;\n } else {\n this.process = spawnResult;\n }\n\n if (!this.process.stdin || !this.process.stdout) {\n throw new Error('Failed to create LSP process with proper stdio');\n }\n\n const reader = new StreamMessageReader(this.process.stdout);\n const writer = new StreamMessageWriter(this.process.stdin);\n this.connection = createMessageConnection(reader, writer);\n\n // Handle connection errors (e.g., ERR_STREAM_DESTROYED during shutdown)\n this.connection.onError(error => {\n // Silently ignore stream destroyed errors during shutdown\n const errorObj = error?.[0] as any;\n if (errorObj?.code !== 'ERR_STREAM_DESTROYED') {\n }\n });\n\n // Set up diagnostic listener before starting connection\n\n this.connection.onNotification('textDocument/publishDiagnostics', (params: any) => {\n if (params.diagnostics && params.diagnostics.length > 0) {\n }\n this.diagnostics.set(params.uri, params.diagnostics);\n });\n (this.connection as any).onNotification((_method: string, _params: any) => {});\n\n this.connection.listen();\n\n // Capture stderr for debugging\n if (this.process.stderr) {\n this.process.stderr.on('data', _data => {});\n }\n\n // Handle process errors\n this.process.on('error', _error => {});\n\n this.process.on('exit', (_code, _signal) => {});\n\n // Send initialize request matching OpenCode's structure\n const initParams: any = {\n processId: process.pid,\n rootUri: `file://${this.workspaceRoot}`,\n workspaceFolders: [\n {\n name: 'workspace',\n uri: `file://${this.workspaceRoot}`,\n },\n ],\n capabilities: {\n window: {\n workDoneProgress: true,\n },\n workspace: {\n configuration: true,\n },\n textDocument: {\n publishDiagnostics: {\n relatedInformation: true,\n tagSupport: {\n valueSet: [1, 2],\n },\n versionSupport: false,\n },\n synchronization: {\n didOpen: true,\n didChange: true,\n dynamicRegistration: false,\n willSave: false,\n willSaveWaitUntil: false,\n didSave: false,\n },\n completion: {\n dynamicRegistration: false,\n completionItem: {\n snippetSupport: false,\n commitCharactersSupport: false,\n documentationFormat: ['markdown', 'plaintext'],\n deprecatedSupport: false,\n preselectSupport: false,\n },\n },\n definition: {\n dynamicRegistration: false,\n linkSupport: true,\n },\n typeDefinition: {\n dynamicRegistration: false,\n linkSupport: true,\n },\n implementation: {\n dynamicRegistration: false,\n linkSupport: true,\n },\n references: {\n dynamicRegistration: false,\n },\n documentHighlight: {\n dynamicRegistration: false,\n },\n documentSymbol: {\n dynamicRegistration: false,\n hierarchicalDocumentSymbolSupport: true,\n },\n codeAction: {\n dynamicRegistration: false,\n codeActionLiteralSupport: {\n codeActionKind: {\n valueSet: [\n 'quickfix',\n 'refactor',\n 'refactor.extract',\n 'refactor.inline',\n 'refactor.rewrite',\n 'source',\n 'source.organizeImports',\n ],\n },\n },\n },\n hover: {\n dynamicRegistration: false,\n contentFormat: ['markdown', 'plaintext'],\n },\n },\n },\n };\n\n // Add initialization options if provided by the server\n if (initializationOptions) {\n initParams.initializationOptions = initializationOptions;\n this.initializationOptions = initializationOptions;\n }\n\n // Add workspace/configuration request handler like OpenCode\n this.connection.onRequest('workspace/configuration', (params: any) => {\n return params.items?.map(() => ({})) || [];\n });\n\n // Handle window/workDoneProgress/create requests\n this.connection.onRequest('window/workDoneProgress/create', (_params: any) => {\n return null;\n });\n\n await Promise.race([\n this.connection.sendRequest('initialize', initParams),\n new Promise((_, reject) => setTimeout(() => reject(new Error('LSP initialize request timed out')), 10000)),\n ]);\n\n // Send initialized notification with empty object like OpenCode\n this.connection.sendNotification('initialized', {});\n\n // Send workspace/didChangeConfiguration with initialization options like OpenCode\n if (this.initializationOptions) {\n this.connection.sendNotification('workspace/didChangeConfiguration', {\n settings: this.initializationOptions,\n });\n } else {\n this.connection.sendNotification('workspace/didChangeConfiguration', {\n settings: {},\n });\n }\n }\n\n /**\n * Notify the server that a document has been opened\n */\n notifyOpen(filePath: string, content: string, languageId: string): void {\n if (!this.connection) return;\n\n const uri = `file://${filePath}`;\n\n // Clear diagnostics for this file before sending didOpen (like OpenCode does)\n this.diagnostics.delete(uri);\n\n this.connection.sendNotification('textDocument/didOpen', {\n textDocument: {\n uri,\n languageId,\n version: 0,\n text: content,\n },\n });\n }\n\n /**\n * Notify the server that a document has changed\n */\n notifyChange(filePath: string, content: string, version: number): void {\n if (!this.connection) return;\n\n this.connection.sendNotification('textDocument/didChange', {\n textDocument: {\n uri: `file://${filePath}`,\n version,\n },\n contentChanges: [{ text: content }],\n });\n }\n\n /**\n * Wait for diagnostics to be available for a specific file\n * @param waitForChange If true, waits for diagnostics to change from their initial state\n */\n async waitForDiagnostics(\n filePath: string,\n timeoutMs: number = 5000,\n waitForChange: boolean = false,\n ): Promise<Diagnostic[]> {\n if (!this.connection) return [];\n\n const uri = `file://${filePath}`;\n const startTime = Date.now();\n const initialDiagnostics = this.diagnostics.get(uri);\n const initialCount = initialDiagnostics?.length || 0;\n\n // Poll for diagnostics to be updated\n while (Date.now() - startTime < timeoutMs) {\n const currentDiagnostics = this.diagnostics.get(uri);\n const currentCount = currentDiagnostics?.length || 0;\n\n // If waiting for change, check if diagnostics have changed\n if (waitForChange) {\n if (currentDiagnostics !== undefined && currentCount !== initialCount) {\n return currentDiagnostics;\n }\n } else {\n // Return if we have diagnostics (even if empty array)\n if (currentDiagnostics !== undefined) {\n return currentDiagnostics;\n }\n }\n\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n\n return waitForChange ? initialDiagnostics || [] : [];\n }\n\n /**\n * Get hover information for a position\n */\n async getHover(filePath: string, line: number, character: number): Promise<any> {\n if (!this.connection) return null;\n\n try {\n return await this.connection.sendRequest('textDocument/hover', {\n textDocument: TextDocumentIdentifier.create(`file://${filePath}`),\n position: Position.create(line, character),\n });\n } catch {\n return null;\n }\n }\n\n /**\n * Get diagnostics for a specific file\n */\n getDiagnostics(filePath: string): Diagnostic[] {\n const uri = `file://${filePath}`;\n return this.diagnostics.get(uri) || [];\n }\n\n /**\n * Get all diagnostics from all files\n */\n getAllDiagnostics(): Diagnostic[] {\n const allDiagnostics: Diagnostic[] = [];\n for (const diagnostics of this.diagnostics.values()) {\n allDiagnostics.push(...diagnostics);\n }\n return allDiagnostics;\n }\n\n /**\n * Notify server that a file was closed\n */\n notifyClose(filePath: string): void {\n if (!this.connection) return;\n\n const uri = `file://${filePath}`;\n\n // Clear diagnostics for this file\n this.diagnostics.delete(uri);\n\n // Send didClose notification\n this.connection.sendNotification('textDocument/didClose', {\n textDocument: TextDocumentIdentifier.create(uri),\n });\n }\n\n /**\n * Restart the LSP client\n */\n async restart(): Promise<void> {\n await this.shutdown();\n\n // Re-initialize (this will re-spawn the server)\n await this.initialize();\n }\n\n /**\n * Shutdown the connection\n */\n async shutdown(): Promise<void> {\n if (this.connection) {\n try {\n // Only send shutdown request if the process is still alive\n const processAlive = this.process && !this.process.killed;\n if (processAlive) {\n await Promise.race([\n this.connection.sendRequest('shutdown'),\n new Promise((_, reject) => setTimeout(() => reject(new Error('Shutdown request timed out')), 1000)),\n ]);\n this.connection.sendNotification('exit');\n }\n } catch {\n // Ignore shutdown errors (process may have already crashed)\n }\n try {\n this.connection.dispose();\n } catch {\n // Ignore dispose errors (stream may already be destroyed)\n }\n this.connection = null;\n }\n\n if (this.process) {\n try {\n if (!this.process.killed) {\n this.process.kill();\n }\n } catch {\n // Ignore kill errors\n }\n this.process = null;\n }\n\n this.diagnostics = new Map();\n }\n}\n"],"mappings":"AACA,SAAS,qBAAqB,qBAAqB,+BAA+B;AAElF,SAAS,wBAAwB,gBAAgB;AAO1C,MAAM,UAAU;AAAA,EACb,aAAuC;AAAA,EACvC,UAA+B;AAAA,EAC/B;AAAA,EACA;AAAA,EACA,cAAyC,oBAAI,IAAI;AAAA,EACjD,wBAA6B;AAAA,EAErC,YAAY,YAA2B,eAAuB;AAC5D,SAAK,aAAa;AAClB,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAA4B;AAChC,UAAM,cAAc,MAAM,KAAK,WAAW,MAAM,KAAK,aAAa;AAElE,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AAGA,QAAI,wBAA6B;AACjC,QAAI,aAAa,aAAa;AAC5B,WAAK,UAAU,YAAY;AAC3B,8BAAwB,YAAY;AAAA,IACtC,OAAO;AACL,WAAK,UAAU;AAAA,IACjB;AAEA,QAAI,CAAC,KAAK,QAAQ,SAAS,CAAC,KAAK,QAAQ,QAAQ;AAC/C,YAAM,IAAI,MAAM,gDAAgD;AAAA,IAClE;AAEA,UAAM,SAAS,IAAI,oBAAoB,KAAK,QAAQ,MAAM;AAC1D,UAAM,SAAS,IAAI,oBAAoB,KAAK,QAAQ,KAAK;AACzD,SAAK,aAAa,wBAAwB,QAAQ,MAAM;AAGxD,SAAK,WAAW,QAAQ,WAAS;AAE/B,YAAM,WAAW,QAAQ,CAAC;AAC1B,UAAI,UAAU,SAAS,wBAAwB;AAAA,MAC/C;AAAA,IACF,CAAC;AAID,SAAK,WAAW,eAAe,mCAAmC,CAAC,WAAgB;AACjF,UAAI,OAAO,eAAe,OAAO,YAAY,SAAS,GAAG;AAAA,MACzD;AACA,WAAK,YAAY,IAAI,OAAO,KAAK,OAAO,WAAW;AAAA,IACrD,CAAC;AACD,IAAC,KAAK,WAAmB,eAAe,CAAC,SAAiB,YAAiB;AAAA,IAAC,CAAC;AAE7E,SAAK,WAAW,OAAO;AAGvB,QAAI,KAAK,QAAQ,QAAQ;AACvB,WAAK,QAAQ,OAAO,GAAG,QAAQ,WAAS;AAAA,MAAC,CAAC;AAAA,IAC5C;AAGA,SAAK,QAAQ,GAAG,SAAS,YAAU;AAAA,IAAC,CAAC;AAErC,SAAK,QAAQ,GAAG,QAAQ,CAAC,OAAO,YAAY;AAAA,IAAC,CAAC;AAG9C,UAAM,aAAkB;AAAA,MACtB,WAAW,QAAQ;AAAA,MACnB,SAAS,UAAU,KAAK,aAAa;AAAA,MACrC,kBAAkB;AAAA,QAChB;AAAA,UACE,MAAM;AAAA,UACN,KAAK,UAAU,KAAK,aAAa;AAAA,QACnC;AAAA,MACF;AAAA,MACA,cAAc;AAAA,QACZ,QAAQ;AAAA,UACN,kBAAkB;AAAA,QACpB;AAAA,QACA,WAAW;AAAA,UACT,eAAe;AAAA,QACjB;AAAA,QACA,cAAc;AAAA,UACZ,oBAAoB;AAAA,YAClB,oBAAoB;AAAA,YACpB,YAAY;AAAA,cACV,UAAU,CAAC,GAAG,CAAC;AAAA,YACjB;AAAA,YACA,gBAAgB;AAAA,UAClB;AAAA,UACA,iBAAiB;AAAA,YACf,SAAS;AAAA,YACT,WAAW;AAAA,YACX,qBAAqB;AAAA,YACrB,UAAU;AAAA,YACV,mBAAmB;AAAA,YACnB,SAAS;AAAA,UACX;AAAA,UACA,YAAY;AAAA,YACV,qBAAqB;AAAA,YACrB,gBAAgB;AAAA,cACd,gBAAgB;AAAA,cAChB,yBAAyB;AAAA,cACzB,qBAAqB,CAAC,YAAY,WAAW;AAAA,cAC7C,mBAAmB;AAAA,cACnB,kBAAkB;AAAA,YACpB;AAAA,UACF;AAAA,UACA,YAAY;AAAA,YACV,qBAAqB;AAAA,YACrB,aAAa;AAAA,UACf;AAAA,UACA,gBAAgB;AAAA,YACd,qBAAqB;AAAA,YACrB,aAAa;AAAA,UACf;AAAA,UACA,gBAAgB;AAAA,YACd,qBAAqB;AAAA,YACrB,aAAa;AAAA,UACf;AAAA,UACA,YAAY;AAAA,YACV,qBAAqB;AAAA,UACvB;AAAA,UACA,mBAAmB;AAAA,YACjB,qBAAqB;AAAA,UACvB;AAAA,UACA,gBAAgB;AAAA,YACd,qBAAqB;AAAA,YACrB,mCAAmC;AAAA,UACrC;AAAA,UACA,YAAY;AAAA,YACV,qBAAqB;AAAA,YACrB,0BAA0B;AAAA,cACxB,gBAAgB;AAAA,gBACd,UAAU;AAAA,kBACR;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,UACA,OAAO;AAAA,YACL,qBAAqB;AAAA,YACrB,eAAe,CAAC,YAAY,WAAW;AAAA,UACzC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,uBAAuB;AACzB,iBAAW,wBAAwB;AACnC,WAAK,wBAAwB;AAAA,IAC/B;AAGA,SAAK,WAAW,UAAU,2BAA2B,CAAC,WAAgB;AACpE,aAAO,OAAO,OAAO,IAAI,OAAO,CAAC,EAAE,KAAK,CAAC;AAAA,IAC3C,CAAC;AAGD,SAAK,WAAW,UAAU,kCAAkC,CAAC,YAAiB;AAC5E,aAAO;AAAA,IACT,CAAC;AAED,UAAM,QAAQ,KAAK;AAAA,MACjB,KAAK,WAAW,YAAY,cAAc,UAAU;AAAA,MACpD,IAAI,QAAQ,CAAC,GAAG,WAAW,WAAW,MAAM,OAAO,IAAI,MAAM,kCAAkC,CAAC,GAAG,GAAK,CAAC;AAAA,IAC3G,CAAC;AAGD,SAAK,WAAW,iBAAiB,eAAe,CAAC,CAAC;AAGlD,QAAI,KAAK,uBAAuB;AAC9B,WAAK,WAAW,iBAAiB,oCAAoC;AAAA,QACnE,UAAU,KAAK;AAAA,MACjB,CAAC;AAAA,IACH,OAAO;AACL,WAAK,WAAW,iBAAiB,oCAAoC;AAAA,QACnE,UAAU,CAAC;AAAA,MACb,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,UAAkB,SAAiB,YAA0B;AACtE,QAAI,CAAC,KAAK,WAAY;AAEtB,UAAM,MAAM,UAAU,QAAQ;AAG9B,SAAK,YAAY,OAAO,GAAG;AAE3B,SAAK,WAAW,iBAAiB,wBAAwB;AAAA,MACvD,cAAc;AAAA,QACZ;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT,MAAM;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,UAAkB,SAAiB,SAAuB;AACrE,QAAI,CAAC,KAAK,WAAY;AAEtB,SAAK,WAAW,iBAAiB,0BAA0B;AAAA,MACzD,cAAc;AAAA,QACZ,KAAK,UAAU,QAAQ;AAAA,QACvB;AAAA,MACF;AAAA,MACA,gBAAgB,CAAC,EAAE,MAAM,QAAQ,CAAC;AAAA,IACpC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,mBACJ,UACA,YAAoB,KACpB,gBAAyB,OACF;AACvB,QAAI,CAAC,KAAK,WAAY,QAAO,CAAC;AAE9B,UAAM,MAAM,UAAU,QAAQ;AAC9B,UAAM,YAAY,KAAK,IAAI;AAC3B,UAAM,qBAAqB,KAAK,YAAY,IAAI,GAAG;AACnD,UAAM,eAAe,oBAAoB,UAAU;AAGnD,WAAO,KAAK,IAAI,IAAI,YAAY,WAAW;AACzC,YAAM,qBAAqB,KAAK,YAAY,IAAI,GAAG;AACnD,YAAM,eAAe,oBAAoB,UAAU;AAGnD,UAAI,eAAe;AACjB,YAAI,uBAAuB,UAAa,iBAAiB,cAAc;AACrE,iBAAO;AAAA,QACT;AAAA,MACF,OAAO;AAEL,YAAI,uBAAuB,QAAW;AACpC,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,YAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,GAAG,CAAC;AAAA,IACvD;AAEA,WAAO,gBAAgB,sBAAsB,CAAC,IAAI,CAAC;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,UAAkB,MAAc,WAAiC;AAC9E,QAAI,CAAC,KAAK,WAAY,QAAO;AAE7B,QAAI;AACF,aAAO,MAAM,KAAK,WAAW,YAAY,sBAAsB;AAAA,QAC7D,cAAc,uBAAuB,OAAO,UAAU,QAAQ,EAAE;AAAA,QAChE,UAAU,SAAS,OAAO,MAAM,SAAS;AAAA,MAC3C,CAAC;AAAA,IACH,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,UAAgC;AAC7C,UAAM,MAAM,UAAU,QAAQ;AAC9B,WAAO,KAAK,YAAY,IAAI,GAAG,KAAK,CAAC;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAkC;AAChC,UAAM,iBAA+B,CAAC;AACtC,eAAW,eAAe,KAAK,YAAY,OAAO,GAAG;AACnD,qBAAe,KAAK,GAAG,WAAW;AAAA,IACpC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,UAAwB;AAClC,QAAI,CAAC,KAAK,WAAY;AAEtB,UAAM,MAAM,UAAU,QAAQ;AAG9B,SAAK,YAAY,OAAO,GAAG;AAG3B,SAAK,WAAW,iBAAiB,yBAAyB;AAAA,MACxD,cAAc,uBAAuB,OAAO,GAAG;AAAA,IACjD,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAyB;AAC7B,UAAM,KAAK,SAAS;AAGpB,UAAM,KAAK,WAAW;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAA0B;AAC9B,QAAI,KAAK,YAAY;AACnB,UAAI;AAEF,cAAM,eAAe,KAAK,WAAW,CAAC,KAAK,QAAQ;AACnD,YAAI,cAAc;AAChB,gBAAM,QAAQ,KAAK;AAAA,YACjB,KAAK,WAAW,YAAY,UAAU;AAAA,YACtC,IAAI,QAAQ,CAAC,GAAG,WAAW,WAAW,MAAM,OAAO,IAAI,MAAM,4BAA4B,CAAC,GAAG,GAAI,CAAC;AAAA,UACpG,CAAC;AACD,eAAK,WAAW,iBAAiB,MAAM;AAAA,QACzC;AAAA,MACF,QAAQ;AAAA,MAER;AACA,UAAI;AACF,aAAK,WAAW,QAAQ;AAAA,MAC1B,QAAQ;AAAA,MAER;AACA,WAAK,aAAa;AAAA,IACpB;AAEA,QAAI,KAAK,SAAS;AAChB,UAAI;AACF,YAAI,CAAC,KAAK,QAAQ,QAAQ;AACxB,eAAK,QAAQ,KAAK;AAAA,QACpB;AAAA,MACF,QAAQ;AAAA,MAER;AACA,WAAK,UAAU;AAAA,IACjB;AAEA,SAAK,cAAc,oBAAI,IAAI;AAAA,EAC7B;AACF;","names":[]}
1
+ {"version":3,"file":"client.js","names":[],"sources":["../../src/lsp/client.ts"],"sourcesContent":["import type { ChildProcess } from 'node:child_process';\nimport { StreamMessageReader, StreamMessageWriter, createMessageConnection } from 'vscode-jsonrpc/node.js';\nimport type { MessageConnection } from 'vscode-jsonrpc/node.js';\nimport { TextDocumentIdentifier, Position } from 'vscode-languageserver-protocol';\nimport type { Diagnostic } from 'vscode-languageserver-protocol';\nimport type { LSPServerInfo } from './server.js';\n\n/**\n * LSP Client wrapper for JSON-RPC communication\n */\nexport class LSPClient {\n private connection: MessageConnection | null = null;\n private process: ChildProcess | null = null;\n private serverInfo: LSPServerInfo;\n private workspaceRoot: string;\n private diagnostics: Map<string, Diagnostic[]> = new Map();\n private initializationOptions: any = null;\n\n constructor(serverInfo: LSPServerInfo, workspaceRoot: string) {\n this.serverInfo = serverInfo;\n this.workspaceRoot = workspaceRoot;\n }\n\n /**\n * Initialize the LSP connection\n */\n async initialize(): Promise<void> {\n const spawnResult = await this.serverInfo.spawn(this.workspaceRoot);\n\n if (!spawnResult) {\n throw new Error('Failed to spawn LSP server');\n }\n\n // Handle both ChildProcess and { process: ChildProcess, initialization? } formats\n let initializationOptions: any = undefined;\n if ('process' in spawnResult) {\n this.process = spawnResult.process;\n initializationOptions = spawnResult.initialization;\n } else {\n this.process = spawnResult;\n }\n\n if (!this.process.stdin || !this.process.stdout) {\n throw new Error('Failed to create LSP process with proper stdio');\n }\n\n const reader = new StreamMessageReader(this.process.stdout);\n const writer = new StreamMessageWriter(this.process.stdin);\n this.connection = createMessageConnection(reader, writer);\n\n // Handle connection errors (e.g., ERR_STREAM_DESTROYED during shutdown)\n this.connection.onError(error => {\n // Silently ignore stream destroyed errors during shutdown\n const errorObj = error?.[0] as any;\n if (errorObj?.code !== 'ERR_STREAM_DESTROYED') {\n }\n });\n\n // Set up diagnostic listener before starting connection\n\n this.connection.onNotification('textDocument/publishDiagnostics', (params: any) => {\n if (params.diagnostics && params.diagnostics.length > 0) {\n }\n this.diagnostics.set(params.uri, params.diagnostics);\n });\n (this.connection as any).onNotification((_method: string, _params: any) => {});\n\n this.connection.listen();\n\n // Capture stderr for debugging\n if (this.process.stderr) {\n this.process.stderr.on('data', _data => {});\n }\n\n // Handle process errors\n this.process.on('error', _error => {});\n\n this.process.on('exit', (_code, _signal) => {});\n\n // Send initialize request matching OpenCode's structure\n const initParams: any = {\n processId: process.pid,\n rootUri: `file://${this.workspaceRoot}`,\n workspaceFolders: [\n {\n name: 'workspace',\n uri: `file://${this.workspaceRoot}`,\n },\n ],\n capabilities: {\n window: {\n workDoneProgress: true,\n },\n workspace: {\n configuration: true,\n },\n textDocument: {\n publishDiagnostics: {\n relatedInformation: true,\n tagSupport: {\n valueSet: [1, 2],\n },\n versionSupport: false,\n },\n synchronization: {\n didOpen: true,\n didChange: true,\n dynamicRegistration: false,\n willSave: false,\n willSaveWaitUntil: false,\n didSave: false,\n },\n completion: {\n dynamicRegistration: false,\n completionItem: {\n snippetSupport: false,\n commitCharactersSupport: false,\n documentationFormat: ['markdown', 'plaintext'],\n deprecatedSupport: false,\n preselectSupport: false,\n },\n },\n definition: {\n dynamicRegistration: false,\n linkSupport: true,\n },\n typeDefinition: {\n dynamicRegistration: false,\n linkSupport: true,\n },\n implementation: {\n dynamicRegistration: false,\n linkSupport: true,\n },\n references: {\n dynamicRegistration: false,\n },\n documentHighlight: {\n dynamicRegistration: false,\n },\n documentSymbol: {\n dynamicRegistration: false,\n hierarchicalDocumentSymbolSupport: true,\n },\n codeAction: {\n dynamicRegistration: false,\n codeActionLiteralSupport: {\n codeActionKind: {\n valueSet: [\n 'quickfix',\n 'refactor',\n 'refactor.extract',\n 'refactor.inline',\n 'refactor.rewrite',\n 'source',\n 'source.organizeImports',\n ],\n },\n },\n },\n hover: {\n dynamicRegistration: false,\n contentFormat: ['markdown', 'plaintext'],\n },\n },\n },\n };\n\n // Add initialization options if provided by the server\n if (initializationOptions) {\n initParams.initializationOptions = initializationOptions;\n this.initializationOptions = initializationOptions;\n }\n\n // Add workspace/configuration request handler like OpenCode\n this.connection.onRequest('workspace/configuration', (params: any) => {\n return params.items?.map(() => ({})) || [];\n });\n\n // Handle window/workDoneProgress/create requests\n this.connection.onRequest('window/workDoneProgress/create', (_params: any) => {\n return null;\n });\n\n await Promise.race([\n this.connection.sendRequest('initialize', initParams),\n new Promise((_, reject) => setTimeout(() => reject(new Error('LSP initialize request timed out')), 10000)),\n ]);\n\n // Send initialized notification with empty object like OpenCode\n this.connection.sendNotification('initialized', {});\n\n // Send workspace/didChangeConfiguration with initialization options like OpenCode\n if (this.initializationOptions) {\n this.connection.sendNotification('workspace/didChangeConfiguration', {\n settings: this.initializationOptions,\n });\n } else {\n this.connection.sendNotification('workspace/didChangeConfiguration', {\n settings: {},\n });\n }\n }\n\n /**\n * Notify the server that a document has been opened\n */\n notifyOpen(filePath: string, content: string, languageId: string): void {\n if (!this.connection) return;\n\n const uri = `file://${filePath}`;\n\n // Clear diagnostics for this file before sending didOpen (like OpenCode does)\n this.diagnostics.delete(uri);\n\n this.connection.sendNotification('textDocument/didOpen', {\n textDocument: {\n uri,\n languageId,\n version: 0,\n text: content,\n },\n });\n }\n\n /**\n * Notify the server that a document has changed\n */\n notifyChange(filePath: string, content: string, version: number): void {\n if (!this.connection) return;\n\n this.connection.sendNotification('textDocument/didChange', {\n textDocument: {\n uri: `file://${filePath}`,\n version,\n },\n contentChanges: [{ text: content }],\n });\n }\n\n /**\n * Wait for diagnostics to be available for a specific file\n * @param waitForChange If true, waits for diagnostics to change from their initial state\n */\n async waitForDiagnostics(\n filePath: string,\n timeoutMs: number = 5000,\n waitForChange: boolean = false,\n ): Promise<Diagnostic[]> {\n if (!this.connection) return [];\n\n const uri = `file://${filePath}`;\n const startTime = Date.now();\n const initialDiagnostics = this.diagnostics.get(uri);\n const initialCount = initialDiagnostics?.length || 0;\n\n // Poll for diagnostics to be updated\n while (Date.now() - startTime < timeoutMs) {\n const currentDiagnostics = this.diagnostics.get(uri);\n const currentCount = currentDiagnostics?.length || 0;\n\n // If waiting for change, check if diagnostics have changed\n if (waitForChange) {\n if (currentDiagnostics !== undefined && currentCount !== initialCount) {\n return currentDiagnostics;\n }\n } else {\n // Return if we have diagnostics (even if empty array)\n if (currentDiagnostics !== undefined) {\n return currentDiagnostics;\n }\n }\n\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n\n return waitForChange ? initialDiagnostics || [] : [];\n }\n\n /**\n * Get hover information for a position\n */\n async getHover(filePath: string, line: number, character: number): Promise<any> {\n if (!this.connection) return null;\n\n try {\n return await this.connection.sendRequest('textDocument/hover', {\n textDocument: TextDocumentIdentifier.create(`file://${filePath}`),\n position: Position.create(line, character),\n });\n } catch {\n return null;\n }\n }\n\n /**\n * Get diagnostics for a specific file\n */\n getDiagnostics(filePath: string): Diagnostic[] {\n const uri = `file://${filePath}`;\n return this.diagnostics.get(uri) || [];\n }\n\n /**\n * Get all diagnostics from all files\n */\n getAllDiagnostics(): Diagnostic[] {\n const allDiagnostics: Diagnostic[] = [];\n for (const diagnostics of this.diagnostics.values()) {\n allDiagnostics.push(...diagnostics);\n }\n return allDiagnostics;\n }\n\n /**\n * Notify server that a file was closed\n */\n notifyClose(filePath: string): void {\n if (!this.connection) return;\n\n const uri = `file://${filePath}`;\n\n // Clear diagnostics for this file\n this.diagnostics.delete(uri);\n\n // Send didClose notification\n this.connection.sendNotification('textDocument/didClose', {\n textDocument: TextDocumentIdentifier.create(uri),\n });\n }\n\n /**\n * Restart the LSP client\n */\n async restart(): Promise<void> {\n await this.shutdown();\n\n // Re-initialize (this will re-spawn the server)\n await this.initialize();\n }\n\n /**\n * Shutdown the connection\n */\n async shutdown(): Promise<void> {\n if (this.connection) {\n try {\n // Only send shutdown request if the process is still alive\n const processAlive = this.process && !this.process.killed;\n if (processAlive) {\n await Promise.race([\n this.connection.sendRequest('shutdown'),\n new Promise((_, reject) => setTimeout(() => reject(new Error('Shutdown request timed out')), 1000)),\n ]);\n this.connection.sendNotification('exit');\n }\n } catch {\n // Ignore shutdown errors (process may have already crashed)\n }\n try {\n this.connection.dispose();\n } catch {\n // Ignore dispose errors (stream may already be destroyed)\n }\n this.connection = null;\n }\n\n if (this.process) {\n try {\n if (!this.process.killed) {\n this.process.kill();\n }\n } catch {\n // Ignore kill errors\n }\n this.process = null;\n }\n\n this.diagnostics = new Map();\n }\n}\n"],"mappings":"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"}