micro-models-agent 0.54.1 → 0.55.1

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 (232) hide show
  1. package/README.md +358 -358
  2. package/dist/certification/certifications.json +493 -493
  3. package/dist/main.js +489 -82
  4. package/dist/modules/browser/bridge-server.mjs +202 -202
  5. package/dist/skills/builtin/git.md +36 -36
  6. package/dist/skills/builtin/typescript.md +35 -35
  7. package/package.json +1 -1
  8. package/dist/cli/commands.js +0 -447
  9. package/dist/cli/completer.js +0 -167
  10. package/dist/cli/index.js +0 -2
  11. package/dist/cli/main.js +0 -153
  12. package/dist/cli/plugin-commands.js +0 -36
  13. package/dist/cli/repl-commands.js +0 -761
  14. package/dist/cli/repl.js +0 -702
  15. package/dist/cli/run-result.js +0 -33
  16. package/dist/cli/security-commands.js +0 -164
  17. package/dist/cli/setup.js +0 -237
  18. package/dist/config/config.js +0 -276
  19. package/dist/config/defaults.js +0 -141
  20. package/dist/config/domains.js +0 -179
  21. package/dist/config/experts.js +0 -15
  22. package/dist/config/index.js +0 -4
  23. package/dist/config/security.js +0 -213
  24. package/dist/config/types.js +0 -1
  25. package/dist/core/agent-moe.js +0 -102
  26. package/dist/core/agent.js +0 -1018
  27. package/dist/core/bootstrap.js +0 -481
  28. package/dist/core/crash-handler.js +0 -51
  29. package/dist/core/environment.js +0 -199
  30. package/dist/core/index.js +0 -2
  31. package/dist/core/prompt-builder.js +0 -76
  32. package/dist/core/session-logger.js +0 -251
  33. package/dist/core/types.js +0 -1
  34. package/dist/core/version.js +0 -26
  35. package/dist/core/workspace.js +0 -76
  36. package/dist/i18n/en.json +0 -679
  37. package/dist/i18n/index.js +0 -46
  38. package/dist/i18n/ru.json +0 -679
  39. package/dist/index.js +0 -22
  40. package/dist/llm/image-utils.js +0 -143
  41. package/dist/llm/index.js +0 -4
  42. package/dist/llm/model-loader.js +0 -78
  43. package/dist/llm/openai-compat.js +0 -497
  44. package/dist/llm/orchestrator.js +0 -200
  45. package/dist/llm/provider.js +0 -10
  46. package/dist/llm/response.js +0 -39
  47. package/dist/llm/token-counter.js +0 -39
  48. package/dist/llm/types.js +0 -1
  49. package/dist/logger/app-logger.js +0 -189
  50. package/dist/logger/file-log.js +0 -151
  51. package/dist/logger/index.js +0 -1
  52. package/dist/migration/backup.js +0 -45
  53. package/dist/migration/detect.js +0 -50
  54. package/dist/migration/index.js +0 -2
  55. package/dist/modules/artifacts/store.js +0 -61
  56. package/dist/modules/browser/actions.js +0 -76
  57. package/dist/modules/browser/bridge-client.js +0 -199
  58. package/dist/modules/browser/bridge-path.js +0 -10
  59. package/dist/modules/browser/cookie-store.js +0 -24
  60. package/dist/modules/browser/driver.js +0 -136
  61. package/dist/modules/browser/index.js +0 -7
  62. package/dist/modules/browser/module.js +0 -29
  63. package/dist/modules/browser/session.js +0 -342
  64. package/dist/modules/browser/snapshot.js +0 -148
  65. package/dist/modules/browser/types.js +0 -12
  66. package/dist/modules/certification/cli.js +0 -213
  67. package/dist/modules/certification/fact-checker.js +0 -82
  68. package/dist/modules/certification/loader.js +0 -106
  69. package/dist/modules/certification/manifest.js +0 -58
  70. package/dist/modules/certification/runner.js +0 -245
  71. package/dist/modules/certification/scenarios.js +0 -407
  72. package/dist/modules/certification/types.js +0 -1
  73. package/dist/modules/context/chunk-query.js +0 -100
  74. package/dist/modules/context/fact-extractor.js +0 -168
  75. package/dist/modules/context/history.js +0 -15
  76. package/dist/modules/context/index.js +0 -1
  77. package/dist/modules/context/manager.js +0 -440
  78. package/dist/modules/execution/audit-runners.js +0 -206
  79. package/dist/modules/execution/auditor.js +0 -218
  80. package/dist/modules/execution/execution-plugin.js +0 -431
  81. package/dist/modules/execution/index.js +0 -8
  82. package/dist/modules/execution/module.js +0 -625
  83. package/dist/modules/execution/moe-executor.js +0 -304
  84. package/dist/modules/execution/plan-coverage.js +0 -68
  85. package/dist/modules/execution/plan-persister.js +0 -46
  86. package/dist/modules/execution/plan-store.js +0 -196
  87. package/dist/modules/execution/plan-tool.js +0 -677
  88. package/dist/modules/execution/plan-validator.js +0 -153
  89. package/dist/modules/execution/planner.js +0 -94
  90. package/dist/modules/execution/stuck-detector.js +0 -746
  91. package/dist/modules/execution/tracker.js +0 -69
  92. package/dist/modules/execution/types.js +0 -1
  93. package/dist/modules/execution/verifier.js +0 -235
  94. package/dist/modules/execution/windows-commands.js +0 -41
  95. package/dist/modules/hallucination/confidence.js +0 -66
  96. package/dist/modules/hallucination/consistency.js +0 -26
  97. package/dist/modules/hallucination/detector.js +0 -47
  98. package/dist/modules/hallucination/factual.js +0 -169
  99. package/dist/modules/hallucination/index.js +0 -5
  100. package/dist/modules/hallucination/js-identifiers.js +0 -262
  101. package/dist/modules/hallucination/llm-judge.js +0 -101
  102. package/dist/modules/index.js +0 -5
  103. package/dist/modules/indexer/cache.js +0 -40
  104. package/dist/modules/indexer/index.js +0 -3
  105. package/dist/modules/indexer/module.js +0 -246
  106. package/dist/modules/indexer/project-profile.js +0 -183
  107. package/dist/modules/indexer/walker.js +0 -101
  108. package/dist/modules/lsp/check-tool.js +0 -58
  109. package/dist/modules/lsp/client.js +0 -389
  110. package/dist/modules/lsp/command.js +0 -60
  111. package/dist/modules/lsp/config.js +0 -135
  112. package/dist/modules/lsp/index.js +0 -3
  113. package/dist/modules/lsp/module.js +0 -260
  114. package/dist/modules/lsp/probe.js +0 -86
  115. package/dist/modules/lsp/project-root.js +0 -32
  116. package/dist/modules/lsp/startup-check.js +0 -144
  117. package/dist/modules/lsp/types.js +0 -1
  118. package/dist/modules/mcp/client.js +0 -399
  119. package/dist/modules/mcp/index.js +0 -3
  120. package/dist/modules/mcp/module.js +0 -142
  121. package/dist/modules/mcp/registry.js +0 -15
  122. package/dist/modules/memory/index.js +0 -1
  123. package/dist/modules/memory/module.js +0 -96
  124. package/dist/modules/memory/search.js +0 -42
  125. package/dist/modules/memory/store.js +0 -69
  126. package/dist/modules/pipelines/engine.js +0 -60
  127. package/dist/modules/pipelines/index.js +0 -3
  128. package/dist/modules/pipelines/parser.js +0 -56
  129. package/dist/modules/pipelines/template.js +0 -14
  130. package/dist/modules/plugins/builtin/lint-on-write.js +0 -334
  131. package/dist/modules/plugins/builtin/notify.js +0 -9
  132. package/dist/modules/plugins/index.js +0 -1
  133. package/dist/modules/plugins/loader.js +0 -70
  134. package/dist/modules/plugins/manager.js +0 -261
  135. package/dist/modules/plugins/types.js +0 -1
  136. package/dist/modules/pricing/index.js +0 -61
  137. package/dist/modules/pricing/prices.js +0 -129
  138. package/dist/modules/processes/detect.js +0 -34
  139. package/dist/modules/processes/index.js +0 -2
  140. package/dist/modules/processes/registry.js +0 -327
  141. package/dist/modules/processes/runner.js +0 -23
  142. package/dist/modules/providers/create.js +0 -22
  143. package/dist/modules/providers/fallback.js +0 -79
  144. package/dist/modules/providers/health.js +0 -46
  145. package/dist/modules/providers/index.js +0 -5
  146. package/dist/modules/providers/manager.js +0 -161
  147. package/dist/modules/providers/presets.js +0 -128
  148. package/dist/modules/providers/registry.js +0 -22
  149. package/dist/modules/providers/types.js +0 -1
  150. package/dist/modules/registry.js +0 -48
  151. package/dist/modules/security/audit-log.js +0 -136
  152. package/dist/modules/security/audit-notifier.js +0 -292
  153. package/dist/modules/security/command-validator.js +0 -219
  154. package/dist/modules/security/content-scanner.js +0 -53
  155. package/dist/modules/security/data-sanitizer.js +0 -89
  156. package/dist/modules/security/encryption.js +0 -242
  157. package/dist/modules/security/index.js +0 -14
  158. package/dist/modules/security/network-validator.js +0 -88
  159. package/dist/modules/security/path-validator.js +0 -203
  160. package/dist/modules/security/rate-limiter.js +0 -119
  161. package/dist/modules/security/security-policies.js +0 -531
  162. package/dist/modules/security/session-encryption.js +0 -210
  163. package/dist/modules/security/session-isolation.js +0 -95
  164. package/dist/modules/session/index.js +0 -3
  165. package/dist/modules/session/manager.js +0 -172
  166. package/dist/modules/session/module.js +0 -24
  167. package/dist/modules/session/store.js +0 -222
  168. package/dist/modules/session/types.js +0 -1
  169. package/dist/modules/skills/index.js +0 -2
  170. package/dist/modules/skills/loader.js +0 -72
  171. package/dist/modules/skills/matcher.js +0 -27
  172. package/dist/modules/skills/module.js +0 -129
  173. package/dist/modules/types.js +0 -1
  174. package/dist/modules/updater/checker.js +0 -96
  175. package/dist/modules/updater/index.js +0 -2
  176. package/dist/modules/updater/module.js +0 -116
  177. package/dist/modules/user-profile/compressor.js +0 -16
  178. package/dist/modules/user-profile/index.js +0 -1
  179. package/dist/modules/user-profile/profile.js +0 -68
  180. package/dist/tools/approve.js +0 -33
  181. package/dist/tools/attach-image.js +0 -101
  182. package/dist/tools/bash.js +0 -519
  183. package/dist/tools/browser.js +0 -115
  184. package/dist/tools/chunk-query.js +0 -100
  185. package/dist/tools/create-dir.js +0 -56
  186. package/dist/tools/delete-file.js +0 -63
  187. package/dist/tools/download-file.js +0 -117
  188. package/dist/tools/edit-file.js +0 -80
  189. package/dist/tools/enable-tools.js +0 -59
  190. package/dist/tools/executor.js +0 -154
  191. package/dist/tools/file-info.js +0 -47
  192. package/dist/tools/filter-tools.js +0 -17
  193. package/dist/tools/glob-tool.js +0 -27
  194. package/dist/tools/grep-tool.js +0 -125
  195. package/dist/tools/hidden-tools-block.js +0 -37
  196. package/dist/tools/index.js +0 -78
  197. package/dist/tools/list-dir.js +0 -49
  198. package/dist/tools/load-skill.js +0 -43
  199. package/dist/tools/mcp-call.js +0 -69
  200. package/dist/tools/move-file.js +0 -86
  201. package/dist/tools/path-utils.js +0 -101
  202. package/dist/tools/pipeline-run.js +0 -145
  203. package/dist/tools/preview.js +0 -2
  204. package/dist/tools/process-kill.js +0 -40
  205. package/dist/tools/process-list.js +0 -37
  206. package/dist/tools/process-log.js +0 -54
  207. package/dist/tools/question.js +0 -141
  208. package/dist/tools/read-file.js +0 -179
  209. package/dist/tools/recall.js +0 -118
  210. package/dist/tools/registry.js +0 -47
  211. package/dist/tools/remember.js +0 -68
  212. package/dist/tools/scope-check.js +0 -32
  213. package/dist/tools/search-history.js +0 -85
  214. package/dist/tools/subagent.js +0 -196
  215. package/dist/tools/types.js +0 -1
  216. package/dist/tools/user-input.js +0 -123
  217. package/dist/tools/web-browse.js +0 -87
  218. package/dist/tools/web-fetch.js +0 -119
  219. package/dist/tools/web-search.js +0 -105
  220. package/dist/tools/write-file.js +0 -82
  221. package/dist/ui/box.js +0 -77
  222. package/dist/ui/colors.js +0 -4
  223. package/dist/ui/diff.js +0 -178
  224. package/dist/ui/index.js +0 -6
  225. package/dist/ui/line-editor.js +0 -822
  226. package/dist/ui/line-math.js +0 -73
  227. package/dist/ui/md-formatter.js +0 -212
  228. package/dist/ui/output.js +0 -13
  229. package/dist/ui/plan-view.js +0 -103
  230. package/dist/ui/renderer.js +0 -259
  231. package/dist/ui/spinner.js +0 -70
  232. package/dist/ui/table.js +0 -144
@@ -1,389 +0,0 @@
1
- import { spawn, execSync } from "child_process";
2
- import { resolve } from "path";
3
- import { platform } from "os";
4
- import { resolveSpawnCommand, buildWinCommandLine } from "./command";
5
- import { killTree } from "../processes/registry";
6
- /**
7
- * Logger adapter that writes LSP diagnostics to app.jsonl only — never to
8
- * console/terminal. LSP warnings are noisy (timeout on first run, npx
9
- * install) and should be diagnosable from session files without polluting
10
- * the user's chat.
11
- */
12
- export class FileOnlyLogger {
13
- logger;
14
- constructor(logger) {
15
- this.logger = logger;
16
- }
17
- debug(msg, meta) {
18
- this.logger.logSilent("debug", msg, meta);
19
- }
20
- info(msg, meta) {
21
- this.logger.logSilent("info", msg, meta);
22
- }
23
- warn(msg, meta) {
24
- this.logger.logSilent("warn", msg, meta);
25
- }
26
- error(msg, meta) {
27
- this.logger.logSilent("error", msg, meta);
28
- }
29
- }
30
- const DEFAULT_TIMEOUT = 15000;
31
- export class LspClient {
32
- logger = null;
33
- setLogger(logger) {
34
- this.logger = logger;
35
- }
36
- process = null;
37
- requestId = 0;
38
- pending = new Map();
39
- buffer = "";
40
- contentLength = -1;
41
- diagnostics = [];
42
- diagnosticsResolve = null;
43
- diagnosticsTimer = null;
44
- initialized = false;
45
- async checkFile(filePath, baseDir, config, projectRoot = baseDir) {
46
- const timeout = config.timeout ?? DEFAULT_TIMEOUT;
47
- try {
48
- await this.initialize(config, projectRoot, timeout);
49
- this.sendNotification("initialized", {});
50
- const uri = this.pathToUri(resolve(filePath));
51
- const fs = await import("fs");
52
- const content = fs.readFileSync(filePath, "utf-8");
53
- const diagPromise = new Promise((resolve) => {
54
- this.diagnosticsResolve = resolve;
55
- this.diagnostics = [];
56
- this.diagnosticsTimer = setTimeout(() => {
57
- this.diagnosticsResolve?.([]);
58
- this.diagnosticsResolve = null;
59
- }, timeout);
60
- });
61
- this.sendNotification("textDocument/didOpen", {
62
- textDocument: {
63
- uri,
64
- languageId: this.languageFromPath(filePath),
65
- version: 1,
66
- text: content,
67
- },
68
- });
69
- return await diagPromise;
70
- }
71
- catch (e) {
72
- // Re-throw so the LspModule can surface failures instead of hiding them.
73
- throw e instanceof Error ? e : new Error(String(e));
74
- }
75
- finally {
76
- await this.shutdown();
77
- }
78
- }
79
- /**
80
- * Lightweight "does the server actually start" probe: spawn + initialize +
81
- * shutdown. Used by the REPL banner to surface a dead server (npx
82
- * auto-install failure, wrong package name, missing binary) up front instead
83
- * of the first write_file timing out.
84
- */
85
- async probe(config, projectRoot, timeout) {
86
- try {
87
- await this.initialize(config, projectRoot, timeout);
88
- }
89
- finally {
90
- await this.shutdown();
91
- }
92
- }
93
- async initialize(config, projectRoot, timeout) {
94
- await this.startServer(config, projectRoot);
95
- const rootUri = this.pathToUri(projectRoot);
96
- const initParams = {
97
- processId: process.pid,
98
- rootUri,
99
- workspaceFolders: [{ uri: rootUri, name: "workspace" }],
100
- capabilities: { textDocument: { publishDiagnostics: {} } },
101
- };
102
- try {
103
- await this.sendRequest("initialize", initParams, timeout);
104
- }
105
- catch (e) {
106
- const msg = e instanceof Error ? e.message : String(e);
107
- this.logger?.warn(`LSP initialize failed (attempt 1): ${msg}`, {
108
- command: config.command,
109
- projectRoot,
110
- });
111
- // npx auto-install can blow past the initialize timeout on first run — retry once.
112
- if (!(e instanceof Error) || !e.message.includes("initialize"))
113
- throw e;
114
- await this.shutdown();
115
- await this.startServer(config, projectRoot);
116
- try {
117
- await this.sendRequest("initialize", initParams, timeout);
118
- }
119
- catch (retryErr) {
120
- const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);
121
- this.logger?.error(`LSP initialize failed (attempt 2, giving up): ${retryMsg}`, {
122
- command: config.command,
123
- projectRoot,
124
- });
125
- throw retryErr;
126
- }
127
- }
128
- this.initialized = true;
129
- }
130
- async startServer(config, projectRoot) {
131
- if (config.autoInstall === false) {
132
- try {
133
- execSync(`where ${config.command}`, { stdio: "pipe", timeout: 3000 });
134
- }
135
- catch {
136
- throw new Error(`${config.command} not found in PATH`);
137
- }
138
- }
139
- // When the command is npx, try to find the actual binary globally first.
140
- // npx downloads packages on every invocation (slow on Windows, ~8-15s),
141
- // even when the binary is already installed globally.
142
- let effectiveCommand = config.command;
143
- let effectiveArgs = config.args ?? [];
144
- if (config.command === "npx" && effectiveArgs.length > 0) {
145
- const binaryName = this.extractBinaryFromNpxArgs(effectiveArgs);
146
- if (binaryName) {
147
- const whichCmd = platform() === "win32" ? `where ${binaryName}` : `which ${binaryName}`;
148
- try {
149
- execSync(whichCmd, { stdio: "pipe", timeout: 3000 });
150
- // Binary found globally — use it directly, skip npx.
151
- effectiveCommand = binaryName;
152
- effectiveArgs = effectiveArgs.filter((a) => a !== "--yes" && a !== "--package" && a !== binaryName && !this.isPackageVersion(a));
153
- this.logger?.debug(`LSP: using globally installed ${binaryName} (skipped npx)`);
154
- }
155
- catch {
156
- // Not found globally — fall back to npx (will auto-install).
157
- this.logger?.debug(`LSP: ${binaryName} not found globally, falling back to npx`);
158
- }
159
- }
160
- }
161
- return new Promise((resolve, reject) => {
162
- const args = effectiveArgs;
163
- const isWin = platform() === "win32";
164
- let spawnCommand = resolveSpawnCommand(effectiveCommand);
165
- let spawnArgs = args;
166
- const spawnOpts = {
167
- stdio: ["pipe", "pipe", "pipe"],
168
- env: { ...process.env, ...config.env },
169
- cwd: projectRoot,
170
- };
171
- if (isWin) {
172
- // A `.cmd` shim can't be spawned directly under Node (`spawn npx EINVAL`) — run via cmd.exe.
173
- spawnCommand = buildWinCommandLine(spawnCommand, args);
174
- spawnArgs = [];
175
- spawnOpts.shell = true;
176
- }
177
- const proc = spawn(spawnCommand, spawnArgs, spawnOpts);
178
- proc.on("error", reject);
179
- proc.stdout.on("data", (chunk) => {
180
- this.handleData(chunk);
181
- });
182
- proc.stderr.on("data", () => { });
183
- proc.once("spawn", () => {
184
- resolve();
185
- });
186
- this.process = proc;
187
- setTimeout(() => {
188
- if (!this.initialized && this.process) {
189
- const msg = "LSP server start timeout";
190
- this.logger?.error(msg, { command: config.command, projectRoot, timeout: config.timeout ?? 10000 });
191
- reject(new Error(msg));
192
- }
193
- }, config.timeout ?? 10000);
194
- });
195
- }
196
- handleData(chunk) {
197
- this.buffer += chunk.toString();
198
- this.parseMessages();
199
- }
200
- parseMessages() {
201
- while (true) {
202
- if (this.contentLength === -1) {
203
- const headerEnd = this.buffer.indexOf("\r\n\r\n");
204
- if (headerEnd === -1)
205
- return;
206
- const header = this.buffer.slice(0, headerEnd);
207
- const match = header.match(/Content-Length: (\d+)/i);
208
- if (!match) {
209
- this.buffer = this.buffer.slice(headerEnd + 4);
210
- this.contentLength = -1;
211
- continue;
212
- }
213
- this.contentLength = parseInt(match[1], 10);
214
- // Guard against malicious/buggy servers sending absurd Content-Length
215
- if (this.contentLength > 10 * 1024 * 1024) {
216
- this.buffer = this.buffer.slice(headerEnd + 4);
217
- this.contentLength = -1;
218
- continue;
219
- }
220
- this.buffer = this.buffer.slice(headerEnd + 4);
221
- }
222
- if (this.buffer.length < this.contentLength)
223
- return;
224
- const body = this.buffer.slice(0, this.contentLength);
225
- this.buffer = this.buffer.slice(this.contentLength);
226
- this.contentLength = -1;
227
- try {
228
- const msg = JSON.parse(body);
229
- this.handleMessage(msg);
230
- }
231
- catch (e) {
232
- this.logger?.debug(`LSP JSON parse error: ${e instanceof Error ? e.message : String(e)}`);
233
- }
234
- }
235
- }
236
- handleMessage(msg) {
237
- if (msg.method === "textDocument/publishDiagnostics") {
238
- const params = msg.params;
239
- if (params?.diagnostics) {
240
- this.diagnostics = params.diagnostics;
241
- if (this.diagnosticsTimer) {
242
- clearTimeout(this.diagnosticsTimer);
243
- this.diagnosticsTimer = null;
244
- }
245
- this.diagnosticsResolve?.(this.diagnostics);
246
- this.diagnosticsResolve = null;
247
- }
248
- return;
249
- }
250
- if (msg.id !== undefined && msg.id !== null) {
251
- const pending = this.pending.get(msg.id);
252
- if (pending) {
253
- this.pending.delete(msg.id);
254
- if (msg.error) {
255
- pending.reject(new Error(String(msg.error.message ?? "LSP error")));
256
- }
257
- else {
258
- pending.resolve(msg.result);
259
- }
260
- }
261
- }
262
- }
263
- sendRequest(method, params, timeout) {
264
- return new Promise((resolve, reject) => {
265
- const id = ++this.requestId;
266
- this.pending.set(id, { resolve, reject });
267
- const message = JSON.stringify({ jsonrpc: "2.0", id, method, params });
268
- this.write(message);
269
- setTimeout(() => {
270
- if (this.pending.has(id)) {
271
- this.pending.delete(id);
272
- const msg = `LSP request timeout: ${method}`;
273
- this.logger?.warn(msg, { method, timeout });
274
- reject(new Error(msg));
275
- }
276
- }, timeout);
277
- });
278
- }
279
- sendNotification(method, params) {
280
- const message = JSON.stringify({ jsonrpc: "2.0", method, params });
281
- this.write(message);
282
- }
283
- write(message) {
284
- if (!this.process?.stdin?.writable) {
285
- this.logger?.debug("LSP write failed: process stdin not writable");
286
- return;
287
- }
288
- const header = `Content-Length: ${Buffer.byteLength(message)}\r\n\r\n`;
289
- try {
290
- this.process.stdin.write(header + message);
291
- }
292
- catch (e) {
293
- this.logger?.debug(`LSP write error: ${e instanceof Error ? e.message : String(e)}`);
294
- }
295
- }
296
- async shutdown() {
297
- try {
298
- if (this.process && this.initialized && this.process.stdin?.writable) {
299
- // Await the shutdown response (with timeout) so the server has time to
300
- // acknowledge before we send exit and kill the process. The old code
301
- // fired shutdown as fire-and-forget, then killed immediately — the
302
- // server never had a chance to reply, producing spurious timeout warnings.
303
- try {
304
- await this.sendRequest("shutdown", null, 3000);
305
- }
306
- catch (e) {
307
- this.logger?.debug(`LSP shutdown request failed: ${e instanceof Error ? e.message : String(e)}`);
308
- }
309
- this.sendNotification("exit", null);
310
- await new Promise((r) => setTimeout(r, 200));
311
- }
312
- }
313
- catch (e) {
314
- this.logger?.debug(`LSP shutdown error: ${e instanceof Error ? e.message : String(e)}`);
315
- }
316
- finally {
317
- if (this.process) {
318
- // The direct child on win32 is the cmd.exe wrapper; killing it alone
319
- // orphans the npx → node → tsserver tree (observed as leaked node
320
- // processes after every check). Tree-kill so the whole chain dies.
321
- try {
322
- killTree(this.process);
323
- }
324
- catch (e) {
325
- this.logger?.debug(`LSP killTree error: ${e instanceof Error ? e.message : String(e)}`);
326
- }
327
- this.process = null;
328
- }
329
- this.initialized = false;
330
- this.buffer = "";
331
- this.contentLength = -1;
332
- if (this.diagnosticsTimer) {
333
- clearTimeout(this.diagnosticsTimer);
334
- this.diagnosticsTimer = null;
335
- }
336
- }
337
- }
338
- pathToUri(filePath) {
339
- const normalized = filePath.replace(/\\/g, "/");
340
- return /^[a-zA-Z]:/.test(normalized) ? `file:///${normalized}` : `file://${normalized}`;
341
- }
342
- languageFromPath(filePath) {
343
- const ext = filePath.split(".").pop()?.toLowerCase();
344
- const map = {
345
- ts: "typescript",
346
- tsx: "typescriptreact",
347
- mts: "typescript",
348
- cts: "typescript",
349
- js: "javascript",
350
- jsx: "javascriptreact",
351
- mjs: "javascript",
352
- cjs: "javascript",
353
- py: "python",
354
- go: "go",
355
- rs: "rust",
356
- json: "json",
357
- html: "html",
358
- css: "css",
359
- scss: "scss",
360
- md: "markdown",
361
- yaml: "yaml",
362
- yml: "yaml",
363
- };
364
- return map[ext ?? ""] ?? "plaintext";
365
- }
366
- /**
367
- * Extract the actual binary name from npx args.
368
- * For `npx --yes --package typescript-language-server --package typescript@5 typescript-language-server --stdio`
369
- * returns `typescript-language-server` (the last non-flag arg before `--stdio`).
370
- */
371
- extractBinaryFromNpxArgs(args) {
372
- // Find the binary: last arg that doesn't start with -- and isn't a package version
373
- for (let i = args.length - 1; i >= 0; i--) {
374
- const arg = args[i];
375
- if (arg === "--stdio")
376
- continue;
377
- if (arg.startsWith("--"))
378
- return null; // unexpected format
379
- if (this.isPackageVersion(arg))
380
- continue;
381
- return arg;
382
- }
383
- return null;
384
- }
385
- /** Check if a string looks like a package version specifier (e.g. "typescript@5"). */
386
- isPackageVersion(s) {
387
- return /^[\w-]+@[\d.+*-]/.test(s);
388
- }
389
- }
@@ -1,60 +0,0 @@
1
- import { delimiter, join } from "path";
2
- import { existsSync } from "fs";
3
- import { platform } from "os";
4
- const WIN_EXTS = [".cmd", ".bat", ".exe", ".com"];
5
- /**
6
- * Resolve the command string passed to `child_process.spawn` on Windows.
7
- *
8
- * Node's `spawn` cannot execute `.cmd`/`.bat` shims directly without a shell,
9
- * and a bare `npx` fails with `spawn npx ENOENT` because on Windows the
10
- * real executable is `npx.cmd`. This returns the first existing shim
11
- * (`npx.cmd`, `npx.bat`, `npx.exe`, ...) found on PATH, or the bare command
12
- * when nothing exists (the spawn will then fail with a meaningful ENOENT).
13
- *
14
- * Non-Windows platforms and commands that already carry an extension or a
15
- * path separator are returned unchanged.
16
- */
17
- export function resolveSpawnCommand(command, platformName = platform(), pathEnv = process.env.PATH ?? "") {
18
- if (platformName !== "win32")
19
- return command;
20
- // Already a path or has an extension — pass through.
21
- if (command.includes("/") ||
22
- command.includes("\\") ||
23
- WIN_EXTS.some((ext) => command.toLowerCase().endsWith(ext))) {
24
- return command;
25
- }
26
- const dirs = pathEnv.split(delimiter).filter(Boolean);
27
- for (const dir of dirs) {
28
- for (const ext of WIN_EXTS) {
29
- const candidate = join(dir, `${command}${ext}`);
30
- if (existsSync(candidate))
31
- return `${command}${ext}`;
32
- }
33
- }
34
- return command;
35
- }
36
- /**
37
- * Join a resolved command and its args into a single cmd.exe command line.
38
- *
39
- * Under Node on Windows, `spawn` of a `.cmd`/`.bat` shim WITHOUT a shell throws
40
- * `spawn EINVAL` (CreateProcess cannot run batch files directly). Resolving
41
- * `npx` → `npx.cmd` fixes the old `ENOENT` but not the `EINVAL` — the spawn
42
- * still has no shell. The reliable fix is to run the whole command line through
43
- * `cmd.exe /d /s /c` (i.e. `spawn(line, { shell: true })`). This helper builds
44
- * that line, quoting any argument that contains cmd.exe metacharacters so the
45
- * package names and flags in LSP configs (`typescript-language-server --stdio`,
46
- * `pyright --stdio`) survive the round-trip.
47
- *
48
- * Non-Windows platforms never call this (they spawn the resolved command +
49
- * args directly, no shell).
50
- */
51
- export function buildWinCommandLine(command, args) {
52
- const quote = (part) => {
53
- if (part === "")
54
- return '""';
55
- if (!/[\s"&|^<>()%!]/.test(part))
56
- return part;
57
- return `"${part.replace(/"/g, '\\"')}"`;
58
- };
59
- return [command, ...args].map(quote).join(" ");
60
- }
@@ -1,135 +0,0 @@
1
- /**
2
- * LSP server defaults.
3
- *
4
- * Strategy: prefer `npx` (auto-downloads) over globally installed binaries.
5
- * Servers using system tools (rust-analyzer, gopls) have `autoInstall: false`
6
- * and are skipped silently when not found.
7
- */
8
- export const DEFAULT_LSP_CONFIG = {
9
- enabled: true,
10
- timeout: 15000,
11
- servers: {
12
- typescript: {
13
- command: "npx",
14
- args: [
15
- "--yes",
16
- "--package",
17
- "typescript-language-server",
18
- "--package",
19
- "typescript@5",
20
- "typescript-language-server",
21
- "--stdio",
22
- ],
23
- timeout: 30000,
24
- autoInstall: true,
25
- workspaceMarkers: ["package.json", "tsconfig.json"],
26
- },
27
- javascript: {
28
- command: "npx",
29
- args: [
30
- "--yes",
31
- "--package",
32
- "typescript-language-server",
33
- "--package",
34
- "typescript@5",
35
- "typescript-language-server",
36
- "--stdio",
37
- ],
38
- timeout: 30000,
39
- autoInstall: true,
40
- workspaceMarkers: ["package.json", "tsconfig.json"],
41
- },
42
- python: {
43
- command: "npx",
44
- args: ["pyright", "--stdio"],
45
- timeout: 15000,
46
- autoInstall: true,
47
- workspaceMarkers: ["pyproject.toml", "setup.py", "requirements.txt"],
48
- },
49
- rust: {
50
- command: "rust-analyzer",
51
- timeout: 15000,
52
- autoInstall: false,
53
- workspaceMarkers: ["Cargo.toml"],
54
- },
55
- go: {
56
- command: "gopls",
57
- timeout: 15000,
58
- autoInstall: false,
59
- workspaceMarkers: ["go.mod"],
60
- },
61
- json: {
62
- command: "npx",
63
- args: [
64
- "--yes",
65
- "--package",
66
- "vscode-langservers-extracted",
67
- "vscode-json-language-server",
68
- "--stdio",
69
- ],
70
- timeout: 30000,
71
- autoInstall: true,
72
- workspaceMarkers: ["package.json"],
73
- },
74
- html: {
75
- command: "npx",
76
- args: [
77
- "--yes",
78
- "--package",
79
- "vscode-langservers-extracted",
80
- "--package",
81
- "typescript@5",
82
- "vscode-html-language-server",
83
- "--stdio",
84
- ],
85
- timeout: 60000,
86
- autoInstall: true,
87
- workspaceMarkers: ["package.json"],
88
- },
89
- css: {
90
- command: "npx",
91
- args: [
92
- "--yes",
93
- "--package",
94
- "vscode-langservers-extracted",
95
- "--package",
96
- "typescript@5",
97
- "vscode-css-language-server",
98
- "--stdio",
99
- ],
100
- timeout: 60000,
101
- autoInstall: true,
102
- workspaceMarkers: ["package.json"],
103
- },
104
- },
105
- };
106
- const LANGUAGE_MAP = {
107
- ts: "typescript",
108
- tsx: "typescript",
109
- mts: "typescript",
110
- cts: "typescript",
111
- js: "javascript",
112
- jsx: "javascript",
113
- mjs: "javascript",
114
- cjs: "javascript",
115
- py: "python",
116
- rs: "rust",
117
- go: "go",
118
- json: "json",
119
- html: "html",
120
- css: "css",
121
- scss: "css",
122
- };
123
- /** Language id for a file extension (via LANGUAGE_MAP), or null when unsupported. */
124
- export function getLanguageForFile(filePath) {
125
- const ext = filePath.split(".").pop()?.toLowerCase();
126
- if (!ext)
127
- return null;
128
- return LANGUAGE_MAP[ext] ?? null;
129
- }
130
- export function getServerForFile(filePath, config) {
131
- const lang = getLanguageForFile(filePath);
132
- if (!lang)
133
- return null;
134
- return config.servers[lang] ?? null;
135
- }
@@ -1,3 +0,0 @@
1
- export { LspModule } from "./module";
2
- export { LspClient, FileOnlyLogger } from "./client";
3
- export { getServerForFile, DEFAULT_LSP_CONFIG } from "./config";