imcp 0.1.3 → 0.1.5
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.
- package/README.md +21 -4
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/pull.js.map +1 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/start.d.ts +2 -0
- package/dist/cli/commands/start.js +32 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/sync.d.ts +2 -0
- package/dist/cli/commands/sync.js +17 -0
- package/dist/cli/commands/sync.js.map +1 -0
- package/dist/cli/commands/uninstall.js.map +1 -0
- package/dist/cli/index.js +0 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/ConfigurationLoader.d.ts +32 -0
- package/{src/core/loaders/ConfigurationLoader.ts → dist/core/ConfigurationLoader.js} +236 -298
- package/dist/core/ConfigurationLoader.js.map +1 -0
- package/dist/core/ConfigurationProvider.d.ts +35 -0
- package/{src/core/loaders/ConfigurationProvider.ts → dist/core/ConfigurationProvider.js} +375 -462
- package/dist/core/ConfigurationProvider.js.map +1 -0
- package/dist/core/InstallationService.d.ts +50 -0
- package/dist/core/InstallationService.js +350 -0
- package/dist/core/InstallationService.js.map +1 -0
- package/dist/core/MCPManager.d.ts +28 -0
- package/dist/core/MCPManager.js +188 -0
- package/dist/core/MCPManager.js.map +1 -0
- package/dist/core/RequirementService.d.ts +40 -0
- package/dist/core/RequirementService.js +110 -0
- package/dist/core/RequirementService.js.map +1 -0
- package/dist/core/ServerSchemaLoader.d.ts +11 -0
- package/dist/core/ServerSchemaLoader.js +43 -0
- package/dist/core/ServerSchemaLoader.js.map +1 -0
- package/dist/core/ServerSchemaProvider.d.ts +17 -0
- package/dist/core/ServerSchemaProvider.js +120 -0
- package/dist/core/ServerSchemaProvider.js.map +1 -0
- package/dist/core/constants.d.ts +47 -0
- package/dist/core/constants.js +94 -0
- package/dist/core/constants.js.map +1 -0
- package/dist/core/installers/BaseInstaller.d.ts +74 -0
- package/dist/core/installers/BaseInstaller.js +253 -0
- package/dist/core/installers/BaseInstaller.js.map +1 -0
- package/dist/core/installers/ClientInstaller.d.ts +23 -0
- package/dist/core/installers/ClientInstaller.js +564 -0
- package/dist/core/installers/ClientInstaller.js.map +1 -0
- package/dist/core/installers/CommandInstaller.d.ts +37 -0
- package/{src/core/installers/requirements/CommandInstaller.ts → dist/core/installers/CommandInstaller.js} +173 -231
- package/dist/core/installers/CommandInstaller.js.map +1 -0
- package/dist/core/installers/GeneralInstaller.d.ts +33 -0
- package/dist/core/installers/GeneralInstaller.js +85 -0
- package/dist/core/installers/GeneralInstaller.js.map +1 -0
- package/dist/core/installers/InstallerFactory.d.ts +54 -0
- package/{src/core/installers/requirements/InstallerFactory.ts → dist/core/installers/InstallerFactory.js} +97 -112
- package/dist/core/installers/InstallerFactory.js.map +1 -0
- package/dist/core/installers/NpmInstaller.d.ts +26 -0
- package/dist/core/installers/NpmInstaller.js +127 -0
- package/dist/core/installers/NpmInstaller.js.map +1 -0
- package/dist/core/installers/PipInstaller.d.ts +28 -0
- package/dist/core/installers/PipInstaller.js +127 -0
- package/dist/core/installers/PipInstaller.js.map +1 -0
- package/{src/core/installers/requirements/RequirementInstaller.ts → dist/core/installers/RequirementInstaller.d.ts} +33 -42
- package/dist/core/installers/RequirementInstaller.js +3 -0
- package/dist/core/installers/RequirementInstaller.js.map +1 -0
- package/dist/core/installers/clients/BaseClientInstaller.js.map +1 -0
- package/dist/core/installers/clients/ClientInstaller.js.map +1 -0
- package/dist/core/installers/clients/ClientInstallerFactory.js.map +1 -0
- package/dist/core/installers/clients/ClineInstaller.js.map +1 -0
- package/dist/core/installers/clients/ExtensionInstaller.js.map +1 -0
- package/dist/core/installers/clients/GithubCopilotInstaller.js.map +1 -0
- package/dist/core/installers/clients/MSRooCodeInstaller.js.map +1 -0
- package/dist/core/installers/index.js.map +1 -0
- package/dist/core/installers/requirements/BaseInstaller.js.map +1 -0
- package/dist/core/installers/requirements/CommandInstaller.js.map +1 -0
- package/dist/core/installers/requirements/GeneralInstaller.js.map +1 -0
- package/dist/core/installers/requirements/InstallerFactory.js +2 -0
- package/dist/core/installers/requirements/InstallerFactory.js.map +1 -0
- package/dist/core/installers/requirements/NpmInstaller.js.map +1 -0
- package/dist/core/installers/requirements/NugetInstaller.d.ts +37 -0
- package/dist/core/installers/requirements/NugetInstaller.js +189 -0
- package/dist/core/installers/requirements/NugetInstaller.js.map +1 -0
- package/dist/core/installers/requirements/PipInstaller.js.map +1 -0
- package/dist/core/installers/requirements/RequirementInstaller.js.map +1 -0
- package/dist/core/loaders/ConfigurationLoader.js.map +1 -0
- package/dist/core/loaders/ConfigurationProvider.js.map +1 -0
- package/dist/core/loaders/InstallOperationManager.js.map +1 -0
- package/dist/core/loaders/ServerSchemaLoader.js.map +1 -0
- package/dist/core/loaders/ServerSchemaProvider.js.map +1 -0
- package/dist/core/loaders/SystemSettingsManager.js.map +1 -0
- package/dist/core/metadatas/constants.js.map +1 -0
- package/dist/core/metadatas/recordingConstants.d.ts +2 -0
- package/dist/core/metadatas/recordingConstants.js +2 -0
- package/dist/core/metadatas/recordingConstants.js.map +1 -0
- package/dist/core/metadatas/types.d.ts +1 -1
- package/dist/core/metadatas/types.js.map +1 -0
- package/dist/core/onboard/FeedOnboardService.js +1 -22
- package/dist/core/onboard/FeedOnboardService.js.map +1 -0
- package/dist/core/onboard/OnboardProcessor.js.map +1 -0
- package/dist/core/onboard/OnboardStatus.js.map +1 -0
- package/dist/core/onboard/OnboardStatusManager.js.map +1 -0
- package/dist/core/types.d.ts +166 -0
- package/dist/core/types.js +16 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/validators/FeedValidator.js.map +1 -0
- package/dist/core/validators/IServerValidator.js.map +1 -0
- package/dist/core/validators/SSEServerValidator.js.map +1 -0
- package/dist/core/validators/ServerValidatorFactory.js.map +1 -0
- package/dist/core/validators/StdioServerValidator.js +5 -5
- package/dist/core/validators/StdioServerValidator.js.map +1 -0
- package/dist/index.js.map +1 -0
- package/dist/services/InstallRequestValidator.d.ts +21 -0
- package/dist/services/InstallRequestValidator.js +99 -0
- package/dist/services/InstallRequestValidator.js.map +1 -0
- package/dist/services/InstallationService.js.map +1 -0
- package/dist/services/MCPManager.js.map +1 -0
- package/dist/services/RequirementService.js.map +1 -0
- package/dist/services/ServerService.js.map +1 -0
- package/dist/services/TelemetryService.js.map +1 -0
- package/dist/utils/UpdateCheckTracker.js.map +1 -0
- package/dist/utils/adoUtils.js.map +1 -0
- package/dist/utils/clientUtils.js.map +1 -0
- package/dist/utils/feedUtils.js.map +1 -0
- package/dist/utils/githubAuth.js.map +1 -0
- package/dist/utils/githubUtils.js.map +1 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/macroExpressionUtils.js.map +1 -0
- package/dist/utils/osUtils.d.ts +11 -0
- package/dist/utils/osUtils.js +100 -0
- package/dist/utils/osUtils.js.map +1 -0
- package/dist/utils/versionUtils.js.map +1 -0
- package/dist/web/contract/serverContract.js.map +1 -0
- package/dist/web/public/index.html +1 -1
- package/dist/web/public/js/modal/installHandler.js +227 -0
- package/dist/web/public/js/modal/loadingUI.js +74 -0
- package/dist/web/public/js/modal/messageQueue.js +101 -45
- package/dist/web/public/js/modal/modalUI.js +214 -0
- package/{src/web/public/js/modal/versionUtils.js → dist/web/public/js/modal/version.js} +1 -1
- package/dist/web/public/js/onboard/templates.js +1 -0
- package/dist/web/public/js/serverCategoryList.js +3 -3
- package/dist/web/public/onboard.html +4 -4
- package/dist/web/server.js.map +1 -0
- package/package.json +5 -1
- package/.github/ISSUE_TEMPLATE/JitAccess.yml +0 -28
- package/.github/acl/access.yml +0 -20
- package/.github/compliance/inventory.yml +0 -5
- package/.github/policies/jit.yml +0 -19
- package/.roo/rules-code/rules.md +0 -88
- package/dist/core/onboard/InstallOperationManager.d.ts +0 -23
- package/dist/core/onboard/InstallOperationManager.js +0 -144
- package/docs/ONBOARDING_PAGE_DESIGN.md +0 -260
- package/docs/Telemetry.md +0 -136
- package/memory-bank/activeContext.md +0 -26
- package/memory-bank/decisionLog.md +0 -91
- package/memory-bank/productContext.md +0 -41
- package/memory-bank/progress.md +0 -35
- package/memory-bank/systemPatterns.md +0 -10
- package/src/cli/commands/install.ts +0 -139
- package/src/cli/commands/list.ts +0 -113
- package/src/cli/commands/pull.ts +0 -16
- package/src/cli/commands/serve.ts +0 -39
- package/src/cli/commands/uninstall.ts +0 -64
- package/src/cli/index.ts +0 -82
- package/src/core/installers/clients/BaseClientInstaller.ts +0 -341
- package/src/core/installers/clients/ClientInstaller.ts +0 -222
- package/src/core/installers/clients/ClientInstallerFactory.ts +0 -43
- package/src/core/installers/clients/ClineInstaller.ts +0 -35
- package/src/core/installers/clients/ExtensionInstaller.ts +0 -165
- package/src/core/installers/clients/GithubCopilotInstaller.ts +0 -79
- package/src/core/installers/clients/MSRooCodeInstaller.ts +0 -32
- package/src/core/installers/index.ts +0 -11
- package/src/core/installers/requirements/BaseInstaller.ts +0 -85
- package/src/core/installers/requirements/GeneralInstaller.ts +0 -133
- package/src/core/installers/requirements/NpmInstaller.ts +0 -271
- package/src/core/installers/requirements/PipInstaller.ts +0 -207
- package/src/core/loaders/InstallOperationManager.ts +0 -367
- package/src/core/loaders/ServerSchemaLoader.ts +0 -117
- package/src/core/loaders/ServerSchemaProvider.ts +0 -99
- package/src/core/loaders/SystemSettingsManager.ts +0 -278
- package/src/core/metadatas/constants.ts +0 -122
- package/src/core/metadatas/recordingConstants.ts +0 -62
- package/src/core/metadatas/types.ts +0 -202
- package/src/core/onboard/FeedOnboardService.ts +0 -524
- package/src/core/onboard/OnboardProcessor.ts +0 -356
- package/src/core/onboard/OnboardStatus.ts +0 -60
- package/src/core/onboard/OnboardStatusManager.ts +0 -416
- package/src/core/validators/FeedValidator.ts +0 -135
- package/src/core/validators/IServerValidator.ts +0 -21
- package/src/core/validators/SSEServerValidator.ts +0 -43
- package/src/core/validators/ServerValidatorFactory.ts +0 -51
- package/src/core/validators/StdioServerValidator.ts +0 -312
- package/src/index.ts +0 -44
- package/src/services/InstallationService.ts +0 -102
- package/src/services/MCPManager.ts +0 -249
- package/src/services/RequirementService.ts +0 -627
- package/src/services/ServerService.ts +0 -161
- package/src/services/TelemetryService.ts +0 -59
- package/src/utils/UpdateCheckTracker.ts +0 -86
- package/src/utils/adoUtils.ts +0 -293
- package/src/utils/clientUtils.ts +0 -72
- package/src/utils/feedUtils.ts +0 -31
- package/src/utils/githubAuth.ts +0 -212
- package/src/utils/githubUtils.ts +0 -164
- package/src/utils/logger.ts +0 -195
- package/src/utils/macroExpressionUtils.ts +0 -104
- package/src/utils/osUtils.ts +0 -597
- package/src/utils/versionUtils.ts +0 -114
- package/src/web/contract/serverContract.ts +0 -74
- package/src/web/public/css/detailsWidget.css +0 -235
- package/src/web/public/css/modal.css +0 -757
- package/src/web/public/css/notifications.css +0 -101
- package/src/web/public/css/onboard.css +0 -107
- package/src/web/public/css/serverCategoryList.css +0 -120
- package/src/web/public/css/serverDetails.css +0 -139
- package/src/web/public/index.html +0 -359
- package/src/web/public/js/api.js +0 -132
- package/src/web/public/js/detailsWidget.js +0 -264
- package/src/web/public/js/flights/flights.js +0 -127
- package/src/web/public/js/modal/index.js +0 -52
- package/src/web/public/js/modal/installModal.js +0 -162
- package/src/web/public/js/modal/installation.js +0 -266
- package/src/web/public/js/modal/loadingModal.js +0 -182
- package/src/web/public/js/modal/modalSetup.js +0 -595
- package/src/web/public/js/modal/modalUtils.js +0 -37
- package/src/web/public/js/modal.js +0 -42
- package/src/web/public/js/notifications.js +0 -137
- package/src/web/public/js/onboard/formProcessor.js +0 -1037
- package/src/web/public/js/onboard/index.js +0 -374
- package/src/web/public/js/onboard/publishHandler.js +0 -172
- package/src/web/public/js/onboard/state.js +0 -76
- package/src/web/public/js/onboard/templates.js +0 -341
- package/src/web/public/js/onboard/uiHandlers.js +0 -1076
- package/src/web/public/js/onboard/validationHandlers.js +0 -493
- package/src/web/public/js/serverCategoryDetails.js +0 -364
- package/src/web/public/js/serverCategoryList.js +0 -241
- package/src/web/public/js/settings.js +0 -314
- package/src/web/public/modal.html +0 -84
- package/src/web/public/onboard.html +0 -296
- package/src/web/public/settings.html +0 -135
- package/src/web/public/styles.css +0 -277
- package/src/web/server.ts +0 -478
- package/tsconfig.json +0 -18
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { Logger } from './logger.js';
|
|
2
|
-
import { getPythonPackagePath, getSystemPythonPackageDirectory, getBrowserPath, getGlobalNPMPackagePath } from './osUtils.js';
|
|
3
|
-
import { ServerInstallOptions } from '../core/metadatas/types.js'; // Adjusted path
|
|
4
|
-
import { SystemSettingsManager } from '../core/loaders/SystemSettingsManager.js';
|
|
5
|
-
import * as fsSync from 'fs';
|
|
6
|
-
import * as path from 'path';
|
|
7
|
-
import { execSync } from 'child_process';
|
|
8
|
-
|
|
9
|
-
export const MACRO_EXPRESSIONS = {
|
|
10
|
-
PYTHON_PACKAGE: '${PYTHON_PACKAGE}',
|
|
11
|
-
NPMPATH: '${NPMPATH}',
|
|
12
|
-
BROWSER_PATH: '${BROWSER_PATH}',
|
|
13
|
-
} as const;
|
|
14
|
-
|
|
15
|
-
// Define a map for macro keys to their resolver functions
|
|
16
|
-
export const MacroResolverFunctions: {
|
|
17
|
-
[key: string]: (finalConfig: any, options: ServerInstallOptions) => Promise<string | undefined>;
|
|
18
|
-
} = {
|
|
19
|
-
[MACRO_EXPRESSIONS.PYTHON_PACKAGE]: resolvePythonPackageMacro,
|
|
20
|
-
[MACRO_EXPRESSIONS.NPMPATH]: resolveNpmPathMacro,
|
|
21
|
-
[MACRO_EXPRESSIONS.BROWSER_PATH]: resolveBrowserPathMacro,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Resolves the path for the ${PYTHON_PACKAGE} macro.
|
|
26
|
-
* It considers the pythonEnv setting and falls back to system Python.
|
|
27
|
-
* Also updates finalConfig.command if it's 'python' and pythonEnv is used.
|
|
28
|
-
* @param finalConfig The configuration object (mutated for command).
|
|
29
|
-
* @param options Server installation options.
|
|
30
|
-
* @returns The resolved Python package path or undefined.
|
|
31
|
-
*/
|
|
32
|
-
export async function resolvePythonPackageMacro(finalConfig: any, options: ServerInstallOptions): Promise<string | undefined> {
|
|
33
|
-
const pythonEnv = options.settings?.pythonEnv;
|
|
34
|
-
if (pythonEnv) {
|
|
35
|
-
Logger.debug(`Python environment specified for ${MACRO_EXPRESSIONS.PYTHON_PACKAGE}: ${pythonEnv}`);
|
|
36
|
-
const pythonDir = getPythonPackagePath(pythonEnv);
|
|
37
|
-
if (pythonDir) {
|
|
38
|
-
if (finalConfig.command === 'python') {
|
|
39
|
-
Logger.debug(`Replacing command 'python' with specified pythonEnv: ${pythonEnv} due to ${MACRO_EXPRESSIONS.PYTHON_PACKAGE} resolution`);
|
|
40
|
-
finalConfig.command = pythonEnv;
|
|
41
|
-
}
|
|
42
|
-
return pythonDir;
|
|
43
|
-
}
|
|
44
|
-
Logger.debug(`Could not determine directory for pythonEnv: ${pythonEnv}. ${MACRO_EXPRESSIONS.PYTHON_PACKAGE} will not be replaced using this path.`);
|
|
45
|
-
return undefined;
|
|
46
|
-
} else {
|
|
47
|
-
Logger.debug(`No Python environment specified. Attempting to find system Python for ${MACRO_EXPRESSIONS.PYTHON_PACKAGE}.`);
|
|
48
|
-
const pythonDir = await getSystemPythonPackageDirectory();
|
|
49
|
-
if (pythonDir) {
|
|
50
|
-
return pythonDir;
|
|
51
|
-
}
|
|
52
|
-
Logger.debug(`Could not find system Python directory for ${MACRO_EXPRESSIONS.PYTHON_PACKAGE}.`);
|
|
53
|
-
return undefined;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Resolves the actual NPM module path.
|
|
59
|
-
* It checks a provided path, then NVM, then global npm.
|
|
60
|
-
* @param providedNpmPath An optional, pre-configured NPM path.
|
|
61
|
-
* @returns The resolved NPM module path or undefined if an error occurs.
|
|
62
|
-
*/
|
|
63
|
-
export function resolveNpmModulePath(providedNpmPath: string | undefined): string {
|
|
64
|
-
if (providedNpmPath) {
|
|
65
|
-
return `${providedNpmPath}/node_modules`;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const globalNpmPath = getGlobalNPMPackagePath();
|
|
69
|
-
Logger.debug(`Resolved ${MACRO_EXPRESSIONS.NPMPATH} via global npm to: ${globalNpmPath}`);
|
|
70
|
-
return globalNpmPath;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Resolves the path to an NPM module for the ${NPMPATH} macro.
|
|
75
|
-
* Uses the resolveNpmModulePath function.
|
|
76
|
-
* @param _finalConfig Not used by this resolver.
|
|
77
|
-
* @param options Server installation options, may contain npmPath.
|
|
78
|
-
* @returns The resolved NPM path or undefined if an error occurs.
|
|
79
|
-
*/
|
|
80
|
-
export async function resolveNpmPathMacro(_finalConfig: any, options: ServerInstallOptions): Promise<string | undefined> {
|
|
81
|
-
Logger.debug(`Resolving ${MACRO_EXPRESSIONS.NPMPATH}. Provided npmPath from settings: ${options.settings?.npmPath}`);
|
|
82
|
-
try {
|
|
83
|
-
return resolveNpmModulePath(options.settings?.npmPath);
|
|
84
|
-
} catch (error) {
|
|
85
|
-
Logger.error(`Failed to resolve ${MACRO_EXPRESSIONS.NPMPATH}:`, error);
|
|
86
|
-
return undefined;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Resolves the path for the ${BROWSER_PATH} macro.
|
|
92
|
-
* @returns The system's browser path or undefined.
|
|
93
|
-
*/
|
|
94
|
-
export async function resolveBrowserPathMacro(): Promise<string | undefined> {
|
|
95
|
-
Logger.debug(`Resolving ${MACRO_EXPRESSIONS.BROWSER_PATH}`);
|
|
96
|
-
try {
|
|
97
|
-
const browserPath = await getBrowserPath();
|
|
98
|
-
Logger.debug(`Resolved ${MACRO_EXPRESSIONS.BROWSER_PATH} to: ${browserPath}`);
|
|
99
|
-
return browserPath;
|
|
100
|
-
} catch (error) {
|
|
101
|
-
Logger.error(`Failed to get system browser path for ${MACRO_EXPRESSIONS.BROWSER_PATH}:`, error);
|
|
102
|
-
return undefined;
|
|
103
|
-
}
|
|
104
|
-
}
|
package/src/utils/osUtils.ts
DELETED
|
@@ -1,597 +0,0 @@
|
|
|
1
|
-
import { OSType } from '../core/metadatas/types.js';
|
|
2
|
-
import os from 'os';
|
|
3
|
-
import { exec } from 'child_process';
|
|
4
|
-
import util from 'util';
|
|
5
|
-
import { Logger } from './logger.js';
|
|
6
|
-
import fs from 'fs';
|
|
7
|
-
import path from 'path';
|
|
8
|
-
import { execSync } from 'child_process';
|
|
9
|
-
import * as fsSync from 'fs';
|
|
10
|
-
|
|
11
|
-
const execAsync = util.promisify(exec);
|
|
12
|
-
|
|
13
|
-
export function getOSType(): OSType {
|
|
14
|
-
const platform = os.platform();
|
|
15
|
-
Logger.debug({
|
|
16
|
-
action: 'get_os_type',
|
|
17
|
-
platform
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
switch (platform) {
|
|
21
|
-
case 'win32':
|
|
22
|
-
return OSType.Windows;
|
|
23
|
-
case 'darwin':
|
|
24
|
-
return OSType.MacOS;
|
|
25
|
-
case 'linux':
|
|
26
|
-
return OSType.Linux;
|
|
27
|
-
default:
|
|
28
|
-
const error = `Unsupported operating system: ${platform}`;
|
|
29
|
-
Logger.error(error);
|
|
30
|
-
throw new Error(error);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export async function installCLI(tool: 'gh' | 'git'): Promise<void> {
|
|
35
|
-
const osType = getOSType();
|
|
36
|
-
Logger.debug({
|
|
37
|
-
action: 'install_cli',
|
|
38
|
-
tool,
|
|
39
|
-
osType
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
switch (osType) {
|
|
44
|
-
case OSType.Windows:
|
|
45
|
-
if (tool === 'git') {
|
|
46
|
-
await execAsync('winget install --id Git.Git -e --source winget --silent');
|
|
47
|
-
} else {
|
|
48
|
-
await execAsync('winget install --id GitHub.cli --silent');
|
|
49
|
-
}
|
|
50
|
-
// Refresh PATH environment variable after installation
|
|
51
|
-
await refreshPathEnv();
|
|
52
|
-
break;
|
|
53
|
-
|
|
54
|
-
case OSType.MacOS:
|
|
55
|
-
if (tool === 'git') {
|
|
56
|
-
await execAsync('brew install git');
|
|
57
|
-
} else {
|
|
58
|
-
await execAsync('brew install gh');
|
|
59
|
-
}
|
|
60
|
-
// On macOS, we may need to source profile files
|
|
61
|
-
if (tool === 'git') {
|
|
62
|
-
await execAsync('source ~/.zshrc || source ~/.bash_profile || source ~/.bashrc || true');
|
|
63
|
-
}
|
|
64
|
-
break;
|
|
65
|
-
|
|
66
|
-
case OSType.Linux:
|
|
67
|
-
if (tool === 'git') {
|
|
68
|
-
await execAsync('sudo apt-get update && sudo apt-get install -y git');
|
|
69
|
-
} else {
|
|
70
|
-
await execAsync('curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null && sudo apt update && sudo apt install -y gh');
|
|
71
|
-
}
|
|
72
|
-
// Source bash profile to refresh PATH
|
|
73
|
-
await execAsync('source ~/.bashrc || source ~/.profile || true');
|
|
74
|
-
break;
|
|
75
|
-
|
|
76
|
-
default:
|
|
77
|
-
throw new Error(`Unsupported operating system for installing ${tool}`);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Wait a moment for system to register the new binaries
|
|
81
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
82
|
-
|
|
83
|
-
Logger.debug({
|
|
84
|
-
action: 'install_cli_success',
|
|
85
|
-
tool,
|
|
86
|
-
osType
|
|
87
|
-
});
|
|
88
|
-
} catch (error) {
|
|
89
|
-
Logger.error('Failed to install CLI tool', {
|
|
90
|
-
tool,
|
|
91
|
-
osType,
|
|
92
|
-
error
|
|
93
|
-
});
|
|
94
|
-
throw error;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Refreshes the PATH environment variable for the current Node.js process
|
|
100
|
-
*/
|
|
101
|
-
export async function refreshPathEnv(): Promise<void> {
|
|
102
|
-
const osType = getOSType();
|
|
103
|
-
Logger.debug({
|
|
104
|
-
action: 'refresh_path_env',
|
|
105
|
-
osType
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
try {
|
|
109
|
-
switch (osType) {
|
|
110
|
-
case OSType.Windows:
|
|
111
|
-
// On Windows, get the PATH from registry
|
|
112
|
-
const { stdout: winPath } = await execAsync('powershell -command "[Environment]::GetEnvironmentVariable(\'Path\', \'Machine\') + \';\' + [Environment]::GetEnvironmentVariable(\'Path\', \'User\')"');
|
|
113
|
-
if (winPath) {
|
|
114
|
-
process.env.PATH = winPath.trim();
|
|
115
|
-
Logger.debug('Refreshed PATH from Windows registry');
|
|
116
|
-
}
|
|
117
|
-
break;
|
|
118
|
-
|
|
119
|
-
case OSType.MacOS:
|
|
120
|
-
case OSType.Linux:
|
|
121
|
-
// On Unix systems, typical installation locations if PATH isn't updated
|
|
122
|
-
const commonPaths = [
|
|
123
|
-
'/usr/local/bin',
|
|
124
|
-
'/usr/bin',
|
|
125
|
-
'/bin',
|
|
126
|
-
'/usr/sbin',
|
|
127
|
-
'/sbin',
|
|
128
|
-
'/usr/local/git/bin',
|
|
129
|
-
'/opt/homebrew/bin', // For M1 Macs
|
|
130
|
-
`${os.homedir()}/.local/bin`
|
|
131
|
-
];
|
|
132
|
-
|
|
133
|
-
// Ensure these paths are in process.env.PATH
|
|
134
|
-
if (process.env.PATH) {
|
|
135
|
-
const currentPaths = process.env.PATH.split(':');
|
|
136
|
-
const newPaths = [...new Set([...currentPaths, ...commonPaths])];
|
|
137
|
-
process.env.PATH = newPaths.join(':');
|
|
138
|
-
Logger.debug('Expanded PATH with common Unix binary locations');
|
|
139
|
-
}
|
|
140
|
-
break;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
Logger.debug({
|
|
144
|
-
action: 'refresh_path_env_success',
|
|
145
|
-
path: process.env.PATH
|
|
146
|
-
});
|
|
147
|
-
} catch (error) {
|
|
148
|
-
Logger.error('Failed to refresh PATH environment variable', error);
|
|
149
|
-
// Continue execution even if PATH refresh fails
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Check if a command is available on the system
|
|
155
|
-
* Handles special cases for VS Code on different platforms
|
|
156
|
-
*/
|
|
157
|
-
export async function isCommandAvailable(command: string): Promise<boolean> {
|
|
158
|
-
try {
|
|
159
|
-
// For VS Code on macOS, check both command-line tool and app bundle
|
|
160
|
-
if (process.platform === 'darwin' && (command === 'code' || command === 'code-insiders')) {
|
|
161
|
-
try {
|
|
162
|
-
// Try which command first
|
|
163
|
-
await execAsync(`which ${command}`);
|
|
164
|
-
return true;
|
|
165
|
-
} catch (error) {
|
|
166
|
-
// If which fails, check application bundles
|
|
167
|
-
const systemVSCodePath = command === 'code' ?
|
|
168
|
-
'/Applications/Visual Studio Code.app' :
|
|
169
|
-
'/Applications/Visual Studio Code - Insiders.app';
|
|
170
|
-
|
|
171
|
-
try {
|
|
172
|
-
// Check system Applications first
|
|
173
|
-
await execAsync(`test -d "${systemVSCodePath}"`);
|
|
174
|
-
return true;
|
|
175
|
-
} catch (error) {
|
|
176
|
-
// If system Applications check fails, try user Applications
|
|
177
|
-
const homedir = process.env.HOME;
|
|
178
|
-
if (homedir) {
|
|
179
|
-
const userVSCodePath = command === 'code' ?
|
|
180
|
-
`${homedir}/Applications/Visual Studio Code.app` :
|
|
181
|
-
`${homedir}/Applications/Visual Studio Code - Insiders.app`;
|
|
182
|
-
|
|
183
|
-
try {
|
|
184
|
-
await execAsync(`test -d "${userVSCodePath}"`);
|
|
185
|
-
return true;
|
|
186
|
-
} catch (error) {
|
|
187
|
-
return false;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return false;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// For Windows, use where command
|
|
196
|
-
if (process.platform === 'win32') {
|
|
197
|
-
await execAsync(`where ${command}`);
|
|
198
|
-
return true;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// For all other cases (Unix-like systems), use which command
|
|
202
|
-
await execAsync(`which ${command}`);
|
|
203
|
-
return true;
|
|
204
|
-
} catch (error) {
|
|
205
|
-
return false;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
export async function isToolInstalled(tool: 'gh' | 'git', retries = 3): Promise<boolean> {
|
|
210
|
-
try {
|
|
211
|
-
Logger.debug({
|
|
212
|
-
action: 'check_tool_installed',
|
|
213
|
-
tool,
|
|
214
|
-
retries
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
// Try to execute tool command
|
|
218
|
-
try {
|
|
219
|
-
await execAsync(`${tool} --version`);
|
|
220
|
-
Logger.debug({
|
|
221
|
-
action: 'check_tool_installed_success',
|
|
222
|
-
tool,
|
|
223
|
-
installed: true
|
|
224
|
-
});
|
|
225
|
-
return true;
|
|
226
|
-
} catch (error) {
|
|
227
|
-
// If we have retries left, refresh PATH and try again
|
|
228
|
-
if (retries > 0) {
|
|
229
|
-
Logger.debug(`${tool} not found, refreshing PATH and retrying...`);
|
|
230
|
-
|
|
231
|
-
// Refresh environment PATH variable
|
|
232
|
-
await refreshPathEnv();
|
|
233
|
-
|
|
234
|
-
// Wait a moment before retrying
|
|
235
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
236
|
-
|
|
237
|
-
// Recursive retry with decremented counter
|
|
238
|
-
return isToolInstalled(tool, retries - 1);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// No retries left, tool is not installed
|
|
242
|
-
Logger.debug({
|
|
243
|
-
action: 'check_tool_installed_success',
|
|
244
|
-
tool,
|
|
245
|
-
installed: false
|
|
246
|
-
});
|
|
247
|
-
return false;
|
|
248
|
-
}
|
|
249
|
-
} catch (error) {
|
|
250
|
-
Logger.error(`Error checking if ${tool} is installed`, error);
|
|
251
|
-
return false;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
export async function openBrowser(url: string): Promise<void> {
|
|
256
|
-
const osType = getOSType();
|
|
257
|
-
Logger.debug({
|
|
258
|
-
action: 'open_browser',
|
|
259
|
-
url,
|
|
260
|
-
osType
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
try {
|
|
264
|
-
switch (osType) {
|
|
265
|
-
case OSType.Windows:
|
|
266
|
-
await execAsync(`start ${url}`);
|
|
267
|
-
break;
|
|
268
|
-
case OSType.MacOS:
|
|
269
|
-
await execAsync(`open ${url}`);
|
|
270
|
-
break;
|
|
271
|
-
case OSType.Linux:
|
|
272
|
-
// Try different commands that might be available
|
|
273
|
-
try {
|
|
274
|
-
await execAsync(`xdg-open ${url}`);
|
|
275
|
-
} catch (error) {
|
|
276
|
-
// Try alternative commands
|
|
277
|
-
try {
|
|
278
|
-
await execAsync(`sensible-browser ${url}`);
|
|
279
|
-
} catch (error) {
|
|
280
|
-
await execAsync(`gnome-open ${url}`);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
break;
|
|
284
|
-
default:
|
|
285
|
-
throw new Error(`Unsupported operating system for opening browser`);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
Logger.debug({
|
|
289
|
-
action: 'open_browser_success',
|
|
290
|
-
url,
|
|
291
|
-
osType
|
|
292
|
-
});
|
|
293
|
-
} catch (error) {
|
|
294
|
-
Logger.error('Failed to open browser', {
|
|
295
|
-
url,
|
|
296
|
-
osType,
|
|
297
|
-
error
|
|
298
|
-
});
|
|
299
|
-
// Don't throw the error - just log it and continue
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
export function getPythonPackagePath(pythonExecutablePath: string): string {
|
|
304
|
-
Logger.debug({
|
|
305
|
-
action: 'get_python_package_path',
|
|
306
|
-
pythonExecutablePath
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
try {
|
|
310
|
-
const dir = path.dirname(pythonExecutablePath);
|
|
311
|
-
const isWindows = process.platform === 'win32';
|
|
312
|
-
|
|
313
|
-
// Handle common Python installation patterns
|
|
314
|
-
if (isWindows) {
|
|
315
|
-
// Windows: Handle different Python installations
|
|
316
|
-
if (dir.endsWith('WindowsApps')) {
|
|
317
|
-
// For Windows Store Python, find the actual Python installation directory
|
|
318
|
-
const entries = fs.readdirSync(dir);
|
|
319
|
-
const pythonDir = entries.find(e => e.startsWith('PythonSoftwareFoundation.Python'));
|
|
320
|
-
if (pythonDir && pythonDir.includes('.')) {
|
|
321
|
-
// Extract version from format like "PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0"
|
|
322
|
-
const parts = pythonDir.split('.');
|
|
323
|
-
const majorVer = parts[2];
|
|
324
|
-
const minorVer = parts[3].split('_')[0];
|
|
325
|
-
const version = majorVer + minorVer; // Combines "3" and "13" to "313"
|
|
326
|
-
const localAppData = process.env.LOCALAPPDATA;
|
|
327
|
-
|
|
328
|
-
if (localAppData) {
|
|
329
|
-
const sitePkgsPath = path.join(
|
|
330
|
-
localAppData,
|
|
331
|
-
'Packages',
|
|
332
|
-
pythonDir,
|
|
333
|
-
'LocalCache',
|
|
334
|
-
'local-packages',
|
|
335
|
-
'Python' + version,
|
|
336
|
-
'site-packages'
|
|
337
|
-
);
|
|
338
|
-
|
|
339
|
-
Logger.debug(`Resolved Windows Store Python site-packages path: ${sitePkgsPath}`);
|
|
340
|
-
return sitePkgsPath;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
Logger.debug('Could not resolve Windows Store Python site-packages path');
|
|
345
|
-
// Fallback to user's site-packages
|
|
346
|
-
return path.join(process.env.APPDATA || '', 'Python', 'Python3', 'site-packages');
|
|
347
|
-
} else if (dir.endsWith('Scripts')) {
|
|
348
|
-
// Virtual environment structure on Windows: <venv>/Scripts/python.exe
|
|
349
|
-
const venvRoot = path.dirname(dir);
|
|
350
|
-
return path.join(venvRoot, 'Lib', 'site-packages');
|
|
351
|
-
} else {
|
|
352
|
-
// System Python or Conda on Windows
|
|
353
|
-
return path.join(dir, 'Lib', 'site-packages');
|
|
354
|
-
}
|
|
355
|
-
} else {
|
|
356
|
-
// Unix systems (MacOS/Linux)
|
|
357
|
-
if (dir.endsWith('bin')) {
|
|
358
|
-
// Virtual environment structure on Unix: <venv>/bin/python
|
|
359
|
-
const venvRoot = path.dirname(dir);
|
|
360
|
-
// Try to find python version-specific site-packages
|
|
361
|
-
const libDir = path.join(venvRoot, 'lib');
|
|
362
|
-
if (fs.existsSync(libDir)) {
|
|
363
|
-
const pythonDirs = fs.readdirSync(libDir).filter(d => d.startsWith('python'));
|
|
364
|
-
if (pythonDirs.length > 0) {
|
|
365
|
-
// Use the first python directory found
|
|
366
|
-
return path.join(libDir, pythonDirs[0], 'site-packages');
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
// Fallback to a generic lib/python3/site-packages if version-specific not found
|
|
370
|
-
return path.join(venvRoot, 'lib', 'python3', 'site-packages');
|
|
371
|
-
} else if (dir.toLowerCase().includes('python')) {
|
|
372
|
-
// System Python or Conda on Unix
|
|
373
|
-
const libDir = path.join(dir, 'lib');
|
|
374
|
-
if (fs.existsSync(libDir)) {
|
|
375
|
-
const pythonDirs = fs.readdirSync(libDir).filter(d => d.startsWith('python'));
|
|
376
|
-
if (pythonDirs.length > 0) {
|
|
377
|
-
// Use the first python directory found
|
|
378
|
-
return path.join(libDir, pythonDirs[0], 'site-packages');
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
// Fallback to a generic lib/python3/site-packages
|
|
382
|
-
return path.join(dir, 'lib', 'python3', 'site-packages');
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
// Default fallback: return the original directory
|
|
387
|
-
Logger.debug('No standard Python directory structure found, using original directory');
|
|
388
|
-
return dir;
|
|
389
|
-
} catch (error) {
|
|
390
|
-
Logger.error('Error getting Python package path', {
|
|
391
|
-
pythonExecutablePath,
|
|
392
|
-
error
|
|
393
|
-
});
|
|
394
|
-
return path.dirname(pythonExecutablePath);
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
export async function getSystemPythonPackageDirectory(): Promise<string | null> {
|
|
399
|
-
const command = process.platform === 'win32' ? 'where python' : 'which python';
|
|
400
|
-
|
|
401
|
-
Logger.debug({
|
|
402
|
-
action: 'get_system_python_package_directory',
|
|
403
|
-
command
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
try {
|
|
407
|
-
const { stdout } = await execAsync(command);
|
|
408
|
-
// Use the first path found, trim whitespace
|
|
409
|
-
const pythonPath = stdout.split('\n')[0].trim();
|
|
410
|
-
if (pythonPath) {
|
|
411
|
-
const packagePath = getPythonPackagePath(pythonPath);
|
|
412
|
-
Logger.debug({
|
|
413
|
-
action: 'get_system_python_package_directory_success',
|
|
414
|
-
pythonPath,
|
|
415
|
-
packagePath
|
|
416
|
-
});
|
|
417
|
-
return packagePath;
|
|
418
|
-
}
|
|
419
|
-
Logger.debug('No Python executable found');
|
|
420
|
-
return null;
|
|
421
|
-
} catch (error) {
|
|
422
|
-
Logger.debug(`Could not find system python using "${command}": ${error}`);
|
|
423
|
-
return null;
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
/**
|
|
427
|
-
* Get the system Python executable path.
|
|
428
|
-
* This function returns the absolute path to the system Python executable (e.g., /Users/penwa/miniconda3/envs/browser-use-temp/bin/python).
|
|
429
|
-
* It uses 'which python' (Unix) or 'where python' (Windows) to locate the executable.
|
|
430
|
-
* @returns {Promise<string | null>} The path to the Python executable, or null if not found.
|
|
431
|
-
*/
|
|
432
|
-
export async function getSystemPythonExecutablePath(): Promise<string | null> {
|
|
433
|
-
const command = process.platform === 'win32' ? 'where python' : 'which python';
|
|
434
|
-
|
|
435
|
-
Logger.debug({
|
|
436
|
-
action: 'get_system_python_executable_path',
|
|
437
|
-
command
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
try {
|
|
441
|
-
const { stdout } = await execAsync(command);
|
|
442
|
-
// Use the first path found, trim whitespace
|
|
443
|
-
const pythonPath = stdout.split('\n')[0].trim();
|
|
444
|
-
if (pythonPath) {
|
|
445
|
-
Logger.debug({
|
|
446
|
-
action: 'get_system_python_executable_path_success',
|
|
447
|
-
pythonPath
|
|
448
|
-
});
|
|
449
|
-
return pythonPath;
|
|
450
|
-
}
|
|
451
|
-
Logger.debug('No Python executable found');
|
|
452
|
-
return null;
|
|
453
|
-
} catch (error) {
|
|
454
|
-
Logger.debug(`Could not find system python using "${command}": ${error}`);
|
|
455
|
-
return null;
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
export async function getBrowserPath(): Promise<string> {
|
|
460
|
-
const osType = getOSType();
|
|
461
|
-
Logger.debug({
|
|
462
|
-
action: 'get_system_browser_path',
|
|
463
|
-
osType
|
|
464
|
-
});
|
|
465
|
-
|
|
466
|
-
try {
|
|
467
|
-
switch (osType) {
|
|
468
|
-
case OSType.Windows: {
|
|
469
|
-
// Check for Edge first
|
|
470
|
-
const edgePaths = [
|
|
471
|
-
`${process.env['PROGRAMFILES(X86)']}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
472
|
-
`${process.env['PROGRAMFILES']}\\Microsoft\\Edge\\Application\\msedge.exe`
|
|
473
|
-
];
|
|
474
|
-
for (const path of edgePaths) {
|
|
475
|
-
if (fs.existsSync(path)) {
|
|
476
|
-
return path;
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
// Then check for Chrome
|
|
481
|
-
const chromePaths = [
|
|
482
|
-
`${process.env['PROGRAMFILES(X86)']}\\Google\\Chrome\\Application\\chrome.exe`,
|
|
483
|
-
`${process.env['PROGRAMFILES']}\\Google\\Chrome\\Application\\chrome.exe`
|
|
484
|
-
];
|
|
485
|
-
for (const path of chromePaths) {
|
|
486
|
-
if (fs.existsSync(path)) {
|
|
487
|
-
return path;
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
break;
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
case OSType.MacOS: {
|
|
494
|
-
// Check for Edge first
|
|
495
|
-
const edgePath = '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge';
|
|
496
|
-
if (fs.existsSync(edgePath)) {
|
|
497
|
-
return edgePath;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
// Then check for Chrome
|
|
501
|
-
const chromePath = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
|
|
502
|
-
if (fs.existsSync(chromePath)) {
|
|
503
|
-
return chromePath;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
// Finally check for Safari
|
|
507
|
-
const safariPath = '/Applications/Safari.app/Contents/MacOS/Safari';
|
|
508
|
-
if (fs.existsSync(safariPath)) {
|
|
509
|
-
return safariPath;
|
|
510
|
-
}
|
|
511
|
-
break;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
case OSType.Linux: {
|
|
515
|
-
// Try Edge first
|
|
516
|
-
try {
|
|
517
|
-
const { stdout: edgePath } = await execAsync('which microsoft-edge');
|
|
518
|
-
if (edgePath.trim()) {
|
|
519
|
-
return edgePath.trim();
|
|
520
|
-
}
|
|
521
|
-
} catch { }
|
|
522
|
-
|
|
523
|
-
// Then try Chrome or Chromium
|
|
524
|
-
try {
|
|
525
|
-
const { stdout: chromePath } = await execAsync('which google-chrome chromium');
|
|
526
|
-
if (chromePath.trim()) {
|
|
527
|
-
return chromePath.trim();
|
|
528
|
-
}
|
|
529
|
-
} catch { }
|
|
530
|
-
break;
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
// If no browser found, throw error
|
|
535
|
-
throw new Error('No supported browser found on the system');
|
|
536
|
-
} catch (error) {
|
|
537
|
-
Logger.error('Failed to get browser path', error);
|
|
538
|
-
throw error;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
/**
|
|
543
|
-
* Get the global NPM path
|
|
544
|
-
* This function checks if NVM is installed and retrieves the global NPM path accordingly.
|
|
545
|
-
* If NVM is not installed, it falls back to the global NPM path.
|
|
546
|
-
* @returns The global NPM path as a string.
|
|
547
|
-
* @throws Error if the NPM path cannot be determined.
|
|
548
|
-
* */
|
|
549
|
-
export function getGlobalNPMPackagePath(): string {
|
|
550
|
-
const nvmHome = process.env.NVM_HOME;
|
|
551
|
-
if (nvmHome) {
|
|
552
|
-
try {
|
|
553
|
-
const nodeVersion = execSync('node -v').toString().trim();
|
|
554
|
-
const nvmNodePath = path.join(nvmHome, nodeVersion);
|
|
555
|
-
// Check if this path exists
|
|
556
|
-
try {
|
|
557
|
-
fsSync.accessSync(nvmNodePath);
|
|
558
|
-
return nvmNodePath;
|
|
559
|
-
} catch (error) {
|
|
560
|
-
Logger.debug(`NVM controlled path doesn't exist: ${nvmNodePath}, will try global npm`);
|
|
561
|
-
}
|
|
562
|
-
} catch (error) {
|
|
563
|
-
Logger.debug(`Error determining Node version for NVM: ${error}, will use global npm`);
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
const globalNpmPath = execSync('npm root -g').toString().trim();
|
|
568
|
-
return globalNpmPath;
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
/**
|
|
573
|
-
* Get the NPM executable path on the current platform (Windows, macOS, Linux).
|
|
574
|
-
* On Windows, uses PowerShell to locate npm. On macOS/Linux, uses 'which' to locate npm.
|
|
575
|
-
* Returns the directory containing the npm executable, or a platform-appropriate default if not found.
|
|
576
|
-
*/
|
|
577
|
-
export async function getNpmExecutablePath(): Promise<string> {
|
|
578
|
-
try {
|
|
579
|
-
if (process.platform === 'win32') {
|
|
580
|
-
const { stdout } = await execAsync('powershell -Command "get-command npm | Select-Object -ExpandProperty Source"');
|
|
581
|
-
return stdout.trim().replace(/\\npm\.cmd$/, '');
|
|
582
|
-
} else {
|
|
583
|
-
// macOS or Linux
|
|
584
|
-
const { stdout } = await execAsync('which npm');
|
|
585
|
-
// Remove the trailing '/npm' to get the directory
|
|
586
|
-
return stdout.trim().replace(/\/npm$/, '');
|
|
587
|
-
}
|
|
588
|
-
} catch (error) {
|
|
589
|
-
Logger.error('Error getting npm path:', error);
|
|
590
|
-
if (process.platform === 'win32') {
|
|
591
|
-
return 'C:\\Program Files\\nodejs';
|
|
592
|
-
} else {
|
|
593
|
-
// Common default for Unix systems
|
|
594
|
-
return '/usr/local/bin';
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
}
|