@vybestack/llxprt-code-ide-integration 0.10.0-nightly.260613.1adad3b34

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 (41) hide show
  1. package/dist/.last_build +0 -0
  2. package/dist/index.d.ts +6 -0
  3. package/dist/index.js +7 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/src/ide/constants.d.ts +6 -0
  6. package/dist/src/ide/constants.js +7 -0
  7. package/dist/src/ide/constants.js.map +1 -0
  8. package/dist/src/ide/detect-ide.d.ts +64 -0
  9. package/dist/src/ide/detect-ide.js +78 -0
  10. package/dist/src/ide/detect-ide.js.map +1 -0
  11. package/dist/src/ide/ide-client.d.ts +77 -0
  12. package/dist/src/ide/ide-client.js +440 -0
  13. package/dist/src/ide/ide-client.js.map +1 -0
  14. package/dist/src/ide/ide-installer.d.ts +14 -0
  15. package/dist/src/ide/ide-installer.js +116 -0
  16. package/dist/src/ide/ide-installer.js.map +1 -0
  17. package/dist/src/ide/ideContext.d.ts +415 -0
  18. package/dist/src/ide/ideContext.js +162 -0
  19. package/dist/src/ide/ideContext.js.map +1 -0
  20. package/dist/src/ide/index.d.ts +11 -0
  21. package/dist/src/ide/index.js +12 -0
  22. package/dist/src/ide/index.js.map +1 -0
  23. package/dist/src/ide/process-utils.d.ts +21 -0
  24. package/dist/src/ide/process-utils.js +198 -0
  25. package/dist/src/ide/process-utils.js.map +1 -0
  26. package/dist/src/index.d.ts +8 -0
  27. package/dist/src/index.js +9 -0
  28. package/dist/src/index.js.map +1 -0
  29. package/dist/src/lsp/index.d.ts +7 -0
  30. package/dist/src/lsp/index.js +7 -0
  31. package/dist/src/lsp/index.js.map +1 -0
  32. package/dist/src/lsp/lsp-service-client.d.ts +37 -0
  33. package/dist/src/lsp/lsp-service-client.js +415 -0
  34. package/dist/src/lsp/lsp-service-client.js.map +1 -0
  35. package/dist/src/lsp/types.d.ts +45 -0
  36. package/dist/src/lsp/types.js +3 -0
  37. package/dist/src/lsp/types.js.map +1 -0
  38. package/dist/src/utils/paths.d.ts +13 -0
  39. package/dist/src/utils/paths.js +24 -0
  40. package/dist/src/utils/paths.js.map +1 -0
  41. package/package.json +46 -0
@@ -0,0 +1,440 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import * as fs from 'node:fs';
7
+ import { isSubpath } from '../utils/paths.js';
8
+ import { detectIde, IDE_DEFINITIONS } from './detect-ide.js';
9
+ import { ideContext, IdeContextNotificationSchema, IdeDiffAcceptedNotificationSchema, IdeDiffRejectedNotificationSchema, IdeDiffClosedNotificationSchema, CloseDiffResponseSchema, } from './ideContext.js';
10
+ import { getIdeProcessInfo } from './process-utils.js';
11
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
12
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
13
+ import * as os from 'node:os';
14
+ import * as path from 'node:path';
15
+ import { EnvHttpProxyAgent, } from 'undici';
16
+ import { debugLogger } from '@vybestack/llxprt-code-telemetry/utils/debugLogger.js';
17
+ const logger = {
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ debug: (...args) => debugLogger.debug('[DEBUG] [IDEClient]', ...args),
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ error: (...args) => debugLogger.error('[ERROR] [IDEClient]', ...args),
22
+ };
23
+ export var IDEConnectionStatus;
24
+ (function (IDEConnectionStatus) {
25
+ IDEConnectionStatus["Connected"] = "connected";
26
+ IDEConnectionStatus["Disconnected"] = "disconnected";
27
+ IDEConnectionStatus["Connecting"] = "connecting";
28
+ })(IDEConnectionStatus || (IDEConnectionStatus = {}));
29
+ function getRealPath(path) {
30
+ try {
31
+ return fs.realpathSync(path);
32
+ }
33
+ catch {
34
+ // Path doesn't exist; return original path.
35
+ return path;
36
+ }
37
+ }
38
+ /**
39
+ * Manages the connection to and interaction with the IDE server.
40
+ */
41
+ export class IdeClient {
42
+ static instance;
43
+ client = undefined;
44
+ state = {
45
+ status: IDEConnectionStatus.Disconnected,
46
+ details: 'IDE integration is currently disabled. To enable it, run /ide enable.',
47
+ };
48
+ currentIde;
49
+ ideProcessInfo;
50
+ connectionConfig;
51
+ authToken;
52
+ diffResponses = new Map();
53
+ statusListeners = new Set();
54
+ trustChangeListeners = new Set();
55
+ constructor() { }
56
+ static async getInstance() {
57
+ if (!IdeClient.instance) {
58
+ const client = new IdeClient();
59
+ client.ideProcessInfo = await getIdeProcessInfo();
60
+ client.connectionConfig = await client.getConnectionConfigFromFile();
61
+ client.currentIde = detectIde(client.ideProcessInfo, client.connectionConfig?.ideInfo);
62
+ IdeClient.instance = client;
63
+ }
64
+ return IdeClient.instance;
65
+ }
66
+ static resetInstance() {
67
+ IdeClient.instance = undefined;
68
+ }
69
+ addStatusChangeListener(listener) {
70
+ this.statusListeners.add(listener);
71
+ }
72
+ removeStatusChangeListener(listener) {
73
+ this.statusListeners.delete(listener);
74
+ }
75
+ addTrustChangeListener(listener) {
76
+ this.trustChangeListeners.add(listener);
77
+ }
78
+ removeTrustChangeListener(listener) {
79
+ this.trustChangeListeners.delete(listener);
80
+ }
81
+ async connect() {
82
+ if (!this.currentIde) {
83
+ this.setState(IDEConnectionStatus.Disconnected, `IDE integration is not supported in your current environment. To use this feature, run LLxprt Code in one of these supported IDEs: ${Object.values(IDE_DEFINITIONS)
84
+ .map((ide) => ide.displayName)
85
+ .join(', ')}`, false);
86
+ return;
87
+ }
88
+ this.setState(IDEConnectionStatus.Connecting);
89
+ this.connectionConfig = await this.getConnectionConfigFromFile();
90
+ this.authToken =
91
+ this.connectionConfig?.authToken ??
92
+ process.env['LLXPRT_CODE_IDE_AUTH_TOKEN'];
93
+ const workspacePath = this.connectionConfig?.workspacePath ??
94
+ process.env['LLXPRT_CODE_IDE_WORKSPACE_PATH'];
95
+ const { isValid, error } = IdeClient.validateWorkspacePath(workspacePath, process.cwd());
96
+ if (!isValid) {
97
+ this.setState(IDEConnectionStatus.Disconnected, error, true);
98
+ return;
99
+ }
100
+ const portFromFile = this.connectionConfig?.port;
101
+ if (portFromFile) {
102
+ const connected = await this.establishConnection(portFromFile);
103
+ if (connected) {
104
+ return;
105
+ }
106
+ }
107
+ const portFromEnv = this.getPortFromEnv();
108
+ if (portFromEnv) {
109
+ const connected = await this.establishConnection(portFromEnv);
110
+ if (connected) {
111
+ return;
112
+ }
113
+ }
114
+ this.setState(IDEConnectionStatus.Disconnected, `Failed to connect to IDE companion extension in ${this.currentIde.displayName}. Please ensure the extension is running. To install the extension, run /ide install.`, true);
115
+ }
116
+ /**
117
+ * A diff is accepted with any modifications if the user performs one of the
118
+ * following actions:
119
+ * - Clicks the checkbox icon in the IDE to accept
120
+ * - Runs `command+shift+p` > "LLxprt Code: Accept Diff in IDE" to accept
121
+ * - Selects "accept" in the CLI UI
122
+ * - Saves the file via `ctrl/command+s`
123
+ *
124
+ * A diff is rejected if the user performs one of the following actions:
125
+ * - Clicks the "x" icon in the IDE
126
+ * - Runs "LLxprt Code: Close Diff in IDE"
127
+ * - Selects "no" in the CLI UI
128
+ * - Closes the file
129
+ */
130
+ async openDiff(filePath, newContent) {
131
+ return new Promise((resolve, reject) => {
132
+ this.diffResponses.set(filePath, resolve);
133
+ logger.debug(`openDiff -> tools/call openDiff for ${filePath}`);
134
+ this.client
135
+ ?.callTool({
136
+ name: `openDiff`,
137
+ arguments: {
138
+ filePath,
139
+ newContent,
140
+ },
141
+ })
142
+ .catch((err) => {
143
+ logger.debug(`openDiff callTool for ${filePath} failed:`, err);
144
+ reject(err);
145
+ });
146
+ });
147
+ }
148
+ async closeDiff(filePath, options) {
149
+ try {
150
+ logger.debug(`closeDiff -> tools/call closeDiff for ${filePath}`);
151
+ const result = await this.client?.callTool({
152
+ name: `closeDiff`,
153
+ arguments: {
154
+ filePath,
155
+ suppressNotification: options?.suppressNotification,
156
+ },
157
+ });
158
+ if (result) {
159
+ const parsed = CloseDiffResponseSchema.parse(result);
160
+ return parsed.content;
161
+ }
162
+ }
163
+ catch (err) {
164
+ logger.debug(`closeDiff callTool for ${filePath} failed:`, err);
165
+ }
166
+ return undefined;
167
+ }
168
+ // Closes the diff. Instead of waiting for a notification,
169
+ // manually resolves the diff resolver as the desired outcome.
170
+ async resolveDiffFromCli(filePath, outcome) {
171
+ const resolver = this.diffResponses.get(filePath);
172
+ const content = await this.closeDiff(filePath, {
173
+ // Suppress notification to avoid race where closing the diff rejects the
174
+ // request.
175
+ suppressNotification: true,
176
+ });
177
+ if (resolver) {
178
+ if (outcome === 'accepted') {
179
+ resolver({ status: 'accepted', content });
180
+ }
181
+ else {
182
+ resolver({ status: 'rejected', content: undefined });
183
+ }
184
+ this.diffResponses.delete(filePath);
185
+ }
186
+ }
187
+ async disconnect() {
188
+ if (this.state.status === IDEConnectionStatus.Disconnected) {
189
+ return;
190
+ }
191
+ for (const filePath of this.diffResponses.keys()) {
192
+ await this.closeDiff(filePath);
193
+ }
194
+ this.diffResponses.clear();
195
+ this.setState(IDEConnectionStatus.Disconnected, 'IDE integration disabled. To enable it again, run /ide enable.');
196
+ void this.client?.close();
197
+ }
198
+ getCurrentIde() {
199
+ return this.currentIde;
200
+ }
201
+ getConnectionStatus() {
202
+ return this.state;
203
+ }
204
+ getDetectedIdeDisplayName() {
205
+ return this.currentIde?.displayName;
206
+ }
207
+ /**
208
+ * Check if diffing functionality is enabled for this IDE client.
209
+ * Returns true when the client is connected and the IDE supports diff operations.
210
+ */
211
+ isDiffingEnabled() {
212
+ return this.state.status === IDEConnectionStatus.Connected;
213
+ }
214
+ setState(status, details, logToConsole = false) {
215
+ const isAlreadyDisconnected = this.state.status === IDEConnectionStatus.Disconnected &&
216
+ status === IDEConnectionStatus.Disconnected;
217
+ // Only update details & log to console if the state wasn't already
218
+ // disconnected, so that the first detail message is preserved.
219
+ if (!isAlreadyDisconnected) {
220
+ this.state = { status, details };
221
+ for (const listener of this.statusListeners) {
222
+ listener(this.state);
223
+ }
224
+ if (details) {
225
+ if (logToConsole) {
226
+ logger.error(details);
227
+ }
228
+ else {
229
+ // We only want to log disconnect messages to debug
230
+ // if they are not already being logged to the console.
231
+ logger.debug(details);
232
+ }
233
+ }
234
+ }
235
+ if (status === IDEConnectionStatus.Disconnected) {
236
+ ideContext.clearIdeContext();
237
+ }
238
+ }
239
+ static validateWorkspacePath(ideWorkspacePath, cwd) {
240
+ if (ideWorkspacePath === undefined) {
241
+ return {
242
+ isValid: false,
243
+ error: `Failed to connect to IDE companion extension. Please ensure the extension is running. To install the extension, run /ide install.`,
244
+ };
245
+ }
246
+ if (ideWorkspacePath === '') {
247
+ return {
248
+ isValid: false,
249
+ error: `To use this feature, please open a workspace folder in your IDE and try again.`,
250
+ };
251
+ }
252
+ const ideWorkspacePaths = ideWorkspacePath.split(path.delimiter);
253
+ const realCwd = getRealPath(cwd);
254
+ const isWithinWorkspace = ideWorkspacePaths.some((workspacePath) => {
255
+ const idePath = getRealPath(workspacePath);
256
+ return isSubpath(idePath, realCwd);
257
+ });
258
+ if (!isWithinWorkspace) {
259
+ return {
260
+ isValid: false,
261
+ error: `Directory mismatch. LLxprt Code is running in a different location than the open workspace in the IDE. Please run the CLI from one of the following directories: ${ideWorkspacePaths.join(', ')}`,
262
+ };
263
+ }
264
+ return { isValid: true };
265
+ }
266
+ getPortFromEnv() {
267
+ const port = process.env['LLXPRT_CODE_IDE_SERVER_PORT'];
268
+ if (!port) {
269
+ return undefined;
270
+ }
271
+ return port;
272
+ }
273
+ async getConnectionConfigFromFile() {
274
+ if (!this.ideProcessInfo) {
275
+ return {};
276
+ }
277
+ // Try new port file location (in subdirectory with port in filename)
278
+ try {
279
+ const portDir = path.join(os.tmpdir(), 'llxprt', 'ide');
280
+ const files = await fs.promises.readdir(portDir);
281
+ const prefix = `llxprt-ide-server-${this.ideProcessInfo.pid}-`;
282
+ const portFile = files.find((file) => file.startsWith(prefix) && file.endsWith('.json'));
283
+ if (portFile) {
284
+ const portFilePath = path.join(portDir, portFile);
285
+ const portFileContents = await fs.promises.readFile(portFilePath, 'utf8');
286
+ const configData = JSON.parse(portFileContents);
287
+ return {
288
+ port: configData?.port?.toString(),
289
+ workspacePath: configData?.workspacePath,
290
+ authToken: configData?.authToken,
291
+ ideInfo: configData?.ideInfo,
292
+ };
293
+ }
294
+ }
295
+ catch {
296
+ // Port file in new location not found; try old location.
297
+ }
298
+ // For backwards compatibility, try old port file location
299
+ try {
300
+ const portFile = path.join(os.tmpdir(), `llxprt-ide-server-${this.ideProcessInfo.pid}.json`);
301
+ const portFileContents = await fs.promises.readFile(portFile, 'utf8');
302
+ const configData = JSON.parse(portFileContents);
303
+ return {
304
+ port: configData?.port?.toString(),
305
+ workspacePath: configData?.workspacePath,
306
+ authToken: configData?.authToken,
307
+ ideInfo: configData?.ideInfo,
308
+ };
309
+ }
310
+ catch {
311
+ // No port file found.
312
+ return {};
313
+ }
314
+ }
315
+ createProxyAwareFetch() {
316
+ // ignore proxy for '127.0.0.1' by default to allow connecting to the ide mcp server
317
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional falsy coalescing: env var may be empty string, both cases need same handling
318
+ const existingNoProxy = process.env['NO_PROXY'] || '';
319
+ const agent = new EnvHttpProxyAgent({
320
+ noProxy: [existingNoProxy, '127.0.0.1'].filter(Boolean).join(','),
321
+ });
322
+ const undiciPromise = import('undici');
323
+ // Suppress unhandled rejection if the promise is not awaited immediately.
324
+ // If the import fails, the error will be thrown when awaiting undiciPromise below.
325
+ undiciPromise.catch(() => { });
326
+ return async (url, init) => {
327
+ const { fetch: fetchFn } = await undiciPromise;
328
+ const fetchOptions = {
329
+ ...init,
330
+ dispatcher: agent,
331
+ };
332
+ const options = fetchOptions;
333
+ const response = await fetchFn(url, options);
334
+ // Convert undici headers to standard headers format
335
+ const headers = {};
336
+ response.headers.forEach((value, key) => {
337
+ headers[key] = value;
338
+ });
339
+ return new Response(response.body, {
340
+ status: response.status,
341
+ statusText: response.statusText,
342
+ headers,
343
+ });
344
+ };
345
+ }
346
+ registerClientHandlers() {
347
+ if (!this.client) {
348
+ return;
349
+ }
350
+ this.client.setNotificationHandler(IdeContextNotificationSchema, (notification) => {
351
+ ideContext.setIdeContext(notification.params);
352
+ const isTrusted = notification.params.workspaceState?.isTrusted;
353
+ if (isTrusted !== undefined) {
354
+ for (const listener of this.trustChangeListeners) {
355
+ listener(isTrusted);
356
+ }
357
+ }
358
+ });
359
+ this.client.onerror = (_error) => {
360
+ this.setState(IDEConnectionStatus.Disconnected, `IDE connection error. The connection was lost unexpectedly. Please try reconnecting by running /ide enable`, true);
361
+ };
362
+ this.client.onclose = () => {
363
+ this.setState(IDEConnectionStatus.Disconnected, `IDE connection error. The connection was lost unexpectedly. Please try reconnecting by running /ide enable`, true);
364
+ };
365
+ this.client.setNotificationHandler(IdeDiffAcceptedNotificationSchema, (notification) => {
366
+ const { filePath, content } = notification.params;
367
+ const resolver = this.diffResponses.get(filePath);
368
+ if (resolver) {
369
+ resolver({ status: 'accepted', content });
370
+ this.diffResponses.delete(filePath);
371
+ }
372
+ else {
373
+ logger.debug(`No resolver found for ${filePath}`);
374
+ }
375
+ });
376
+ this.client.setNotificationHandler(IdeDiffRejectedNotificationSchema, (notification) => {
377
+ const { filePath } = notification.params;
378
+ const resolver = this.diffResponses.get(filePath);
379
+ if (resolver) {
380
+ resolver({ status: 'rejected', content: undefined });
381
+ this.diffResponses.delete(filePath);
382
+ }
383
+ else {
384
+ logger.debug(`No resolver found for ${filePath}`);
385
+ }
386
+ });
387
+ // For backwards compatibility. Newer extension versions will only send
388
+ // IdeDiffRejectedNotificationSchema.
389
+ this.client.setNotificationHandler(IdeDiffClosedNotificationSchema, (notification) => {
390
+ const { filePath } = notification.params;
391
+ const resolver = this.diffResponses.get(filePath);
392
+ if (resolver) {
393
+ resolver({ status: 'rejected', content: undefined });
394
+ this.diffResponses.delete(filePath);
395
+ }
396
+ else {
397
+ logger.debug(`No resolver found for ${filePath}`);
398
+ }
399
+ });
400
+ }
401
+ async establishConnection(port) {
402
+ let transport;
403
+ try {
404
+ this.client = new Client({
405
+ name: 'streamable-http-client',
406
+ // Task(#3487): use the CLI version here.
407
+ version: '1.0.0',
408
+ });
409
+ transport = new StreamableHTTPClientTransport(new URL(`http://${getIdeServerHost()}:${port}/mcp`), {
410
+ fetch: this.createProxyAwareFetch(),
411
+ requestInit: {
412
+ headers: this.authToken
413
+ ? { Authorization: `Bearer ${this.authToken}` }
414
+ : {},
415
+ },
416
+ });
417
+ await this.client.connect(transport);
418
+ this.registerClientHandlers();
419
+ this.setState(IDEConnectionStatus.Connected);
420
+ return true;
421
+ }
422
+ catch {
423
+ // Connection failed; cleanup transport if created.
424
+ if (transport) {
425
+ try {
426
+ await transport.close();
427
+ }
428
+ catch (closeError) {
429
+ logger.debug('Failed to close transport:', closeError);
430
+ }
431
+ }
432
+ return false;
433
+ }
434
+ }
435
+ }
436
+ function getIdeServerHost() {
437
+ const isInContainer = fs.existsSync('/.dockerenv') || fs.existsSync('/run/.containerenv');
438
+ return isInContainer ? 'host.docker.internal' : '127.0.0.1';
439
+ }
440
+ //# sourceMappingURL=ide-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ide-client.js","sourceRoot":"","sources":["../../../src/ide/ide-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { type IdeInfo } from './detect-ide.js';
7
+ export interface IdeInstaller {
8
+ install(): Promise<InstallResult>;
9
+ }
10
+ export interface InstallResult {
11
+ success: boolean;
12
+ message: string;
13
+ }
14
+ export declare function getIdeInstaller(ide: IdeInfo, platform?: NodeJS.Platform): IdeInstaller | null;
@@ -0,0 +1,116 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import * as child_process from 'node:child_process';
7
+ import * as process from 'node:process';
8
+ import * as path from 'node:path';
9
+ import * as fs from 'node:fs';
10
+ import * as os from 'node:os';
11
+ import { IDE_DEFINITIONS } from './detect-ide.js';
12
+ import { LLXPRT_CODE_COMPANION_EXTENSION_NAME } from './constants.js';
13
+ function getVsCodeCommand(platform = process.platform) {
14
+ return platform === 'win32' ? 'code.cmd' : 'code';
15
+ }
16
+ async function findVsCodeCommand(platform = process.platform) {
17
+ // 1. Check PATH first.
18
+ const vscodeCommand = getVsCodeCommand(platform);
19
+ try {
20
+ if (platform === 'win32') {
21
+ // eslint-disable-next-line sonarjs/os-command -- Project intentionally invokes platform tooling at this trusted boundary; arguments remain explicit and behavior is preserved.
22
+ const result = child_process
23
+ .execSync(`where.exe ${vscodeCommand}`)
24
+ .toString()
25
+ .trim();
26
+ // `where.exe` can return multiple paths. Return the first one.
27
+ const firstPath = result.split(/\r?\n/)[0];
28
+ if (firstPath) {
29
+ return firstPath;
30
+ }
31
+ }
32
+ else {
33
+ // eslint-disable-next-line sonarjs/os-command -- Project intentionally invokes platform tooling at this trusted boundary; arguments remain explicit and behavior is preserved.
34
+ child_process.execSync(`command -v ${vscodeCommand}`, {
35
+ stdio: 'ignore',
36
+ });
37
+ return vscodeCommand;
38
+ }
39
+ }
40
+ catch {
41
+ // Not in PATH, continue to check common locations.
42
+ }
43
+ // 2. Check common installation locations.
44
+ const locations = [];
45
+ const homeDir = os.homedir();
46
+ if (platform === 'darwin') {
47
+ // macOS
48
+ locations.push('/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code', path.join(homeDir, 'Library/Application Support/Code/bin/code'));
49
+ }
50
+ else if (platform === 'linux') {
51
+ // Linux
52
+ locations.push('/usr/share/code/bin/code', '/snap/bin/code', path.join(homeDir, '.local/share/code/bin/code'));
53
+ }
54
+ else if (platform === 'win32') {
55
+ // Windows
56
+ locations.push(path.join(
57
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional falsy coalescing: env var may be empty string, fallback to default path
58
+ process.env.ProgramFiles || 'C:\\Program Files', 'Microsoft VS Code', 'bin', 'code.cmd'), path.join(homeDir, 'AppData', 'Local', 'Programs', 'Microsoft VS Code', 'bin', 'code.cmd'));
59
+ }
60
+ for (const location of locations) {
61
+ if (fs.existsSync(location)) {
62
+ return location;
63
+ }
64
+ }
65
+ return null;
66
+ }
67
+ class VsCodeInstaller {
68
+ ideInfo;
69
+ platform;
70
+ vsCodeCommand;
71
+ constructor(ideInfo, platform = process.platform) {
72
+ this.ideInfo = ideInfo;
73
+ this.platform = platform;
74
+ this.vsCodeCommand = findVsCodeCommand(platform);
75
+ }
76
+ async install() {
77
+ const commandPath = await this.vsCodeCommand;
78
+ if (!commandPath) {
79
+ return {
80
+ success: false,
81
+ message: `${this.ideInfo.displayName} CLI not found. Please ensure 'code' is in your system's PATH. For help, see https://code.visualstudio.com/docs/configure/command-line#_code-is-not-recognized-as-an-internal-or-external-command. You can also install the '${LLXPRT_CODE_COMPANION_EXTENSION_NAME}' extension manually from the VS Code marketplace.`,
82
+ };
83
+ }
84
+ try {
85
+ const result = child_process.spawnSync(commandPath, [
86
+ '--install-extension',
87
+ 'vybestack.llxprt-code-vscode-ide-companion',
88
+ '--force',
89
+ ], { stdio: 'pipe', shell: this.platform === 'win32' });
90
+ if (result.status !== 0) {
91
+ throw new Error(`Failed to install extension: ${result.stderr.toString()}`);
92
+ }
93
+ return {
94
+ success: true,
95
+ message: `${this.ideInfo.displayName} companion extension was installed successfully.`,
96
+ };
97
+ }
98
+ catch {
99
+ // Extension installation failed - user must install manually
100
+ return {
101
+ success: false,
102
+ message: `Failed to install ${this.ideInfo.displayName} companion extension. Please try installing '${LLXPRT_CODE_COMPANION_EXTENSION_NAME}' manually from the ${this.ideInfo.displayName} extension marketplace.`,
103
+ };
104
+ }
105
+ }
106
+ }
107
+ export function getIdeInstaller(ide, platform = process.platform) {
108
+ switch (ide.name) {
109
+ case IDE_DEFINITIONS.vscode.name:
110
+ case IDE_DEFINITIONS.firebasestudio.name:
111
+ return new VsCodeInstaller(ide, platform);
112
+ default:
113
+ return null;
114
+ }
115
+ }
116
+ //# sourceMappingURL=ide-installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ide-installer.js","sourceRoot":"","sources":["../../../src/ide/ide-installer.ts"],"names":[],"mappings":"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"}