imcp 0.1.1 → 0.1.3
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/dist/cli/index.js +1 -45
- package/dist/core/installers/clients/BaseClientInstaller.d.ts +1 -5
- package/dist/core/installers/clients/BaseClientInstaller.js +40 -38
- package/dist/core/installers/clients/ClientInstaller.d.ts +9 -9
- package/dist/core/installers/clients/ClientInstaller.js +105 -99
- package/dist/core/installers/requirements/BaseInstaller.d.ts +9 -1
- package/dist/core/installers/requirements/CommandInstaller.d.ts +9 -1
- package/dist/core/installers/requirements/CommandInstaller.js +46 -12
- package/dist/core/installers/requirements/GeneralInstaller.d.ts +11 -1
- package/dist/core/installers/requirements/GeneralInstaller.js +46 -10
- package/dist/core/installers/requirements/InstallerFactory.d.ts +3 -1
- package/dist/core/installers/requirements/InstallerFactory.js +3 -2
- package/dist/core/installers/requirements/NpmInstaller.d.ts +4 -2
- package/dist/core/installers/requirements/NpmInstaller.js +38 -22
- package/dist/core/installers/requirements/PipInstaller.d.ts +3 -1
- package/dist/core/installers/requirements/PipInstaller.js +58 -36
- package/dist/core/installers/requirements/RequirementInstaller.d.ts +4 -1
- package/dist/core/loaders/InstallOperationManager.d.ts +115 -0
- package/dist/core/loaders/InstallOperationManager.js +311 -0
- package/dist/core/loaders/SystemSettingsManager.d.ts +54 -0
- package/dist/core/loaders/SystemSettingsManager.js +257 -0
- package/dist/core/metadatas/recordingConstants.d.ts +44 -0
- package/dist/core/metadatas/recordingConstants.js +45 -0
- package/dist/core/metadatas/types.d.ts +21 -0
- package/dist/core/onboard/InstallOperationManager.d.ts +23 -0
- package/dist/core/onboard/InstallOperationManager.js +144 -0
- package/dist/core/onboard/OnboardStatusManager.js +2 -1
- package/dist/core/validators/StdioServerValidator.js +4 -3
- package/dist/services/InstallationService.d.ts +2 -37
- package/dist/services/InstallationService.js +45 -313
- package/dist/services/MCPManager.d.ts +1 -1
- package/dist/services/MCPManager.js +4 -58
- package/dist/services/RequirementService.d.ts +85 -12
- package/dist/services/RequirementService.js +488 -49
- package/dist/services/ServerService.d.ts +0 -6
- package/dist/services/ServerService.js +0 -74
- package/dist/utils/adoUtils.js +6 -3
- package/dist/utils/logger.js +1 -1
- package/dist/utils/macroExpressionUtils.js +3 -25
- package/dist/utils/osUtils.d.ts +22 -1
- package/dist/utils/osUtils.js +92 -1
- package/dist/utils/versionUtils.d.ts +20 -1
- package/dist/utils/versionUtils.js +51 -4
- package/dist/web/public/css/modal.css +292 -1
- package/dist/web/public/css/serverDetails.css +14 -1
- package/dist/web/public/index.html +122 -20
- package/dist/web/public/js/flights/flights.js +1 -0
- package/dist/web/public/js/modal/index.js +8 -14
- package/dist/web/public/js/modal/installModal.js +3 -4
- package/dist/web/public/js/modal/installation.js +122 -137
- package/dist/web/public/js/modal/loadingModal.js +155 -25
- package/dist/web/public/js/modal/messageQueue.js +45 -101
- package/dist/web/public/js/modal/modalSetup.js +125 -43
- package/dist/web/public/js/modal/modalUtils.js +0 -12
- package/dist/web/public/js/modal.js +23 -10
- package/dist/web/public/js/onboard/publishHandler.js +22 -20
- package/dist/web/public/js/serverCategoryDetails.js +60 -11
- package/dist/web/public/js/serverCategoryList.js +2 -2
- package/dist/web/public/js/settings.js +314 -0
- package/dist/web/public/settings.html +135 -0
- package/dist/web/public/styles.css +32 -0
- package/dist/web/server.js +82 -0
- package/memory-bank/activeContext.md +13 -1
- package/memory-bank/decisionLog.md +63 -0
- package/memory-bank/progress.md +30 -0
- package/memory-bank/systemPatterns.md +7 -0
- package/package.json +1 -1
- package/src/cli/index.ts +1 -48
- package/src/core/installers/clients/BaseClientInstaller.ts +64 -50
- package/src/core/installers/clients/ClientInstaller.ts +130 -130
- package/src/core/installers/requirements/BaseInstaller.ts +9 -1
- package/src/core/installers/requirements/CommandInstaller.ts +47 -13
- package/src/core/installers/requirements/GeneralInstaller.ts +48 -10
- package/src/core/installers/requirements/InstallerFactory.ts +4 -3
- package/src/core/installers/requirements/NpmInstaller.ts +90 -68
- package/src/core/installers/requirements/PipInstaller.ts +81 -55
- package/src/core/installers/requirements/RequirementInstaller.ts +4 -3
- package/src/core/loaders/InstallOperationManager.ts +367 -0
- package/src/core/loaders/SystemSettingsManager.ts +278 -0
- package/src/core/metadatas/recordingConstants.ts +62 -0
- package/src/core/metadatas/types.ts +23 -0
- package/src/core/onboard/OnboardStatusManager.ts +2 -1
- package/src/core/validators/StdioServerValidator.ts +4 -3
- package/src/services/InstallationService.ts +54 -399
- package/src/services/MCPManager.ts +4 -77
- package/src/services/RequirementService.ts +564 -67
- package/src/services/ServerService.ts +0 -90
- package/src/utils/adoUtils.ts +6 -4
- package/src/utils/logger.ts +1 -1
- package/src/utils/macroExpressionUtils.ts +4 -21
- package/src/utils/osUtils.ts +92 -1
- package/src/utils/versionUtils.ts +71 -19
- package/src/web/public/css/modal.css +292 -1
- package/src/web/public/css/serverDetails.css +14 -1
- package/src/web/public/index.html +122 -20
- package/src/web/public/js/flights/flights.js +1 -1
- package/src/web/public/js/modal/index.js +8 -14
- package/src/web/public/js/modal/installModal.js +3 -4
- package/src/web/public/js/modal/installation.js +122 -137
- package/src/web/public/js/modal/loadingModal.js +155 -25
- package/src/web/public/js/modal/modalSetup.js +125 -43
- package/src/web/public/js/modal/modalUtils.js +0 -12
- package/src/web/public/js/modal.js +23 -10
- package/src/web/public/js/onboard/publishHandler.js +22 -20
- package/src/web/public/js/serverCategoryDetails.js +60 -11
- package/src/web/public/js/serverCategoryList.js +5 -5
- package/src/web/public/js/settings.js +314 -0
- package/src/web/public/settings.html +135 -0
- package/src/web/public/styles.css +32 -0
- package/src/web/server.ts +85 -0
- package/src/web/public/js/modal/messageQueue.js +0 -112
|
@@ -3,8 +3,6 @@ import { fileURLToPath } from 'url';
|
|
|
3
3
|
import { Logger } from '../utils/logger.js';
|
|
4
4
|
import { ServerSchemaProvider } from '../core/loaders/ServerSchemaProvider.js';
|
|
5
5
|
import { mcpManager } from './MCPManager.js';
|
|
6
|
-
import { UPDATE_CHECK_INTERVAL_MS } from '../core/metadatas/constants.js';
|
|
7
|
-
import { updateCheckTracker } from '../utils/UpdateCheckTracker.js';
|
|
8
6
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
7
|
/**
|
|
10
8
|
* ServerService provides a unified interface for server management operations.
|
|
@@ -23,80 +21,8 @@ export class ServerService {
|
|
|
23
21
|
async getServerCategory(categoryName) {
|
|
24
22
|
const serverCategories = await this.listServerCategories();
|
|
25
23
|
const serverCategory = serverCategories.find(s => s.name === categoryName);
|
|
26
|
-
// Start async check for requirement updates if one isn't already in progress
|
|
27
|
-
if (serverCategory && serverCategory.feedConfiguration && serverCategory.name) {
|
|
28
|
-
// Check if update is already in progress using the tracker
|
|
29
|
-
const shouldCheckForUpdates = await updateCheckTracker.startOperation(serverCategory.name);
|
|
30
|
-
if (shouldCheckForUpdates) {
|
|
31
|
-
this.checkRequirementsForUpdate(serverCategory).catch(error => {
|
|
32
|
-
// Ensure we mark the operation as complete on error
|
|
33
|
-
if (serverCategory.name) {
|
|
34
|
-
updateCheckTracker.endOperation(serverCategory.name)
|
|
35
|
-
.catch(lockError => console.error(`Failed to mark update check as complete: ${lockError.message}`));
|
|
36
|
-
}
|
|
37
|
-
Logger.error(`Error checking requirements for updates: ${error.message}`);
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
Logger.debug(`Update check already in progress for ${serverCategory.name}, skipping`);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
24
|
return serverCategory;
|
|
45
25
|
}
|
|
46
|
-
/**
|
|
47
|
-
* Check for updates to requirements for a server category
|
|
48
|
-
* @param serverCategory The server category to check
|
|
49
|
-
* @private
|
|
50
|
-
*/
|
|
51
|
-
async checkRequirementsForUpdate(serverCategory) {
|
|
52
|
-
if (!serverCategory.name || !serverCategory.feedConfiguration?.requirements?.length) {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
try {
|
|
56
|
-
const { requirementService } = await import('./RequirementService.js');
|
|
57
|
-
const { configProvider } = await import('../core/loaders/ConfigurationProvider.js');
|
|
58
|
-
for (const requirement of serverCategory.feedConfiguration.requirements) {
|
|
59
|
-
if (requirement.version.includes('latest')) {
|
|
60
|
-
// Get current status if available
|
|
61
|
-
const currentStatus = serverCategory.installationStatus?.requirementsStatus[requirement.name];
|
|
62
|
-
if (!currentStatus)
|
|
63
|
-
continue;
|
|
64
|
-
// Skip update check if last check was less than UPDATE_CHECK_INTERVAL_MS ago
|
|
65
|
-
if (currentStatus.lastCheckTime) {
|
|
66
|
-
const lastCheckTime = new Date(currentStatus.lastCheckTime);
|
|
67
|
-
const currentTime = new Date();
|
|
68
|
-
const timeSinceLastCheck = currentTime.getTime() - lastCheckTime.getTime();
|
|
69
|
-
if (timeSinceLastCheck < UPDATE_CHECK_INTERVAL_MS) {
|
|
70
|
-
Logger.debug(`Skipping update check for ${requirement.name}, last check was ${Math.round(timeSinceLastCheck / 1000)} seconds ago`);
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
// Check for updates
|
|
75
|
-
const updatedStatus = await requirementService.checkRequirementForUpdates(requirement, currentStatus);
|
|
76
|
-
// If update information is found, update the configuration
|
|
77
|
-
if (updatedStatus.availableUpdate && serverCategory.name) {
|
|
78
|
-
await configProvider.updateRequirementStatus(serverCategory.name, requirement.name, updatedStatus);
|
|
79
|
-
// Also update the in-memory status for immediate use
|
|
80
|
-
if (serverCategory.installationStatus?.requirementsStatus) {
|
|
81
|
-
serverCategory.installationStatus.requirementsStatus[requirement.name] = updatedStatus;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
currentStatus.lastCheckTime = new Date().toISOString();
|
|
85
|
-
await configProvider.updateRequirementStatus(serverCategory.name, requirement.name, currentStatus);
|
|
86
|
-
if (serverCategory.installationStatus?.requirementsStatus) {
|
|
87
|
-
serverCategory.installationStatus.requirementsStatus[requirement.name] = updatedStatus;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
finally {
|
|
93
|
-
// Always mark the operation as complete when done, even if there was an error
|
|
94
|
-
if (serverCategory.name) {
|
|
95
|
-
await updateCheckTracker.endOperation(serverCategory.name)
|
|
96
|
-
.catch(error => console.error(`Failed to mark update check as complete: ${error.message}`));
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
26
|
/**
|
|
101
27
|
* Gets the schema for a specific server in a category
|
|
102
28
|
*/
|
package/dist/utils/adoUtils.js
CHANGED
|
@@ -104,11 +104,11 @@ targetDir // Optional target directory for npm
|
|
|
104
104
|
if (!registry) {
|
|
105
105
|
throw new Error('Azure DevOps artifacts registry configuration is required.');
|
|
106
106
|
}
|
|
107
|
-
if (!registry.registryName || !registry.registryUrl) {
|
|
108
|
-
throw new Error('Registry name and URL are required for Azure DevOps artifacts.');
|
|
109
|
-
}
|
|
110
107
|
Logger.debug(`Handling ADO artifact for requirement: ${requirement.name}, type: ${requirement.type}`);
|
|
111
108
|
if (requirement.type === 'npm') {
|
|
109
|
+
if (!registry.registryName || !registry.registryUrl) {
|
|
110
|
+
throw new Error('Registry name and URL are required for NPM source in Azure DevOps artifacts.');
|
|
111
|
+
}
|
|
112
112
|
const requirementDir = targetDir || path.join(SETTINGS_DIR, 'requirements', requirement.name, requirement.version);
|
|
113
113
|
await fs.mkdir(requirementDir, { recursive: true });
|
|
114
114
|
Logger.debug(`Ensured directory for npm requirement: ${requirementDir}`);
|
|
@@ -130,6 +130,9 @@ targetDir // Optional target directory for npm
|
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
else if (requirement.type === 'pip') {
|
|
133
|
+
if (!registry.registryUrl) {
|
|
134
|
+
throw new Error('Registry URL are required for PIP source in Azure DevOps artifacts.');
|
|
135
|
+
}
|
|
133
136
|
await _installPipRequirements(pythonCommand);
|
|
134
137
|
const packageName = requirement.version.toLowerCase().includes('latest')
|
|
135
138
|
? `${requirement.name} --upgrade`
|
package/dist/utils/logger.js
CHANGED
|
@@ -23,7 +23,7 @@ export class Logger {
|
|
|
23
23
|
static fileLoggingEnabled = true;
|
|
24
24
|
static logsDir = path.join(SETTINGS_DIR, 'logs');
|
|
25
25
|
static isTestEnvironment = false;
|
|
26
|
-
static packageVersion = getPackageVersion();
|
|
26
|
+
static packageVersion = getPackageVersion().packageVersion;
|
|
27
27
|
static setVerbose(isVerbose) {
|
|
28
28
|
this.verbose = isVerbose;
|
|
29
29
|
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { Logger } from './logger.js';
|
|
2
|
-
import { getPythonPackagePath, getSystemPythonPackageDirectory,
|
|
3
|
-
import * as fsSync from 'fs';
|
|
4
|
-
import * as path from 'path';
|
|
5
|
-
import { execSync } from 'child_process';
|
|
2
|
+
import { getPythonPackagePath, getSystemPythonPackageDirectory, getBrowserPath, getGlobalNPMPackagePath } from './osUtils.js';
|
|
6
3
|
export const MACRO_EXPRESSIONS = {
|
|
7
4
|
PYTHON_PACKAGE: '${PYTHON_PACKAGE}',
|
|
8
5
|
NPMPATH: '${NPMPATH}',
|
|
@@ -57,26 +54,7 @@ export function resolveNpmModulePath(providedNpmPath) {
|
|
|
57
54
|
if (providedNpmPath) {
|
|
58
55
|
return `${providedNpmPath}/node_modules`;
|
|
59
56
|
}
|
|
60
|
-
const
|
|
61
|
-
if (nvmHome) {
|
|
62
|
-
try {
|
|
63
|
-
const nodeVersion = execSync('node -v').toString().trim();
|
|
64
|
-
const nvmNodePath = path.join(nvmHome, nodeVersion);
|
|
65
|
-
// Check if this path exists
|
|
66
|
-
try {
|
|
67
|
-
fsSync.accessSync(nvmNodePath);
|
|
68
|
-
Logger.debug(`Resolved ${MACRO_EXPRESSIONS.NPMPATH} via NVM to: ${nvmNodePath}`);
|
|
69
|
-
return nvmNodePath;
|
|
70
|
-
}
|
|
71
|
-
catch (error) {
|
|
72
|
-
Logger.debug(`NVM controlled path doesn't exist: ${nvmNodePath}, will try global npm`);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
Logger.debug(`Error determining Node version for NVM: ${error}, will use global npm`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
const globalNpmPath = execSync('npm root -g').toString().trim();
|
|
57
|
+
const globalNpmPath = getGlobalNPMPackagePath();
|
|
80
58
|
Logger.debug(`Resolved ${MACRO_EXPRESSIONS.NPMPATH} via global npm to: ${globalNpmPath}`);
|
|
81
59
|
return globalNpmPath;
|
|
82
60
|
}
|
|
@@ -104,7 +82,7 @@ export async function resolveNpmPathMacro(_finalConfig, options) {
|
|
|
104
82
|
export async function resolveBrowserPathMacro() {
|
|
105
83
|
Logger.debug(`Resolving ${MACRO_EXPRESSIONS.BROWSER_PATH}`);
|
|
106
84
|
try {
|
|
107
|
-
const browserPath = await
|
|
85
|
+
const browserPath = await getBrowserPath();
|
|
108
86
|
Logger.debug(`Resolved ${MACRO_EXPRESSIONS.BROWSER_PATH} to: ${browserPath}`);
|
|
109
87
|
return browserPath;
|
|
110
88
|
}
|
package/dist/utils/osUtils.d.ts
CHANGED
|
@@ -14,4 +14,25 @@ export declare function isToolInstalled(tool: 'gh' | 'git', retries?: number): P
|
|
|
14
14
|
export declare function openBrowser(url: string): Promise<void>;
|
|
15
15
|
export declare function getPythonPackagePath(pythonExecutablePath: string): string;
|
|
16
16
|
export declare function getSystemPythonPackageDirectory(): Promise<string | null>;
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Get the system Python executable path.
|
|
19
|
+
* This function returns the absolute path to the system Python executable (e.g., /Users/penwa/miniconda3/envs/browser-use-temp/bin/python).
|
|
20
|
+
* It uses 'which python' (Unix) or 'where python' (Windows) to locate the executable.
|
|
21
|
+
* @returns {Promise<string | null>} The path to the Python executable, or null if not found.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getSystemPythonExecutablePath(): Promise<string | null>;
|
|
24
|
+
export declare function getBrowserPath(): Promise<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Get the global NPM path
|
|
27
|
+
* This function checks if NVM is installed and retrieves the global NPM path accordingly.
|
|
28
|
+
* If NVM is not installed, it falls back to the global NPM path.
|
|
29
|
+
* @returns The global NPM path as a string.
|
|
30
|
+
* @throws Error if the NPM path cannot be determined.
|
|
31
|
+
* */
|
|
32
|
+
export declare function getGlobalNPMPackagePath(): string;
|
|
33
|
+
/**
|
|
34
|
+
* Get the NPM executable path on the current platform (Windows, macOS, Linux).
|
|
35
|
+
* On Windows, uses PowerShell to locate npm. On macOS/Linux, uses 'which' to locate npm.
|
|
36
|
+
* Returns the directory containing the npm executable, or a platform-appropriate default if not found.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getNpmExecutablePath(): Promise<string>;
|
package/dist/utils/osUtils.js
CHANGED
|
@@ -5,6 +5,8 @@ import util from 'util';
|
|
|
5
5
|
import { Logger } from './logger.js';
|
|
6
6
|
import fs from 'fs';
|
|
7
7
|
import path from 'path';
|
|
8
|
+
import { execSync } from 'child_process';
|
|
9
|
+
import * as fsSync from 'fs';
|
|
8
10
|
const execAsync = util.promisify(exec);
|
|
9
11
|
export function getOSType() {
|
|
10
12
|
const platform = os.platform();
|
|
@@ -394,7 +396,38 @@ export async function getSystemPythonPackageDirectory() {
|
|
|
394
396
|
return null;
|
|
395
397
|
}
|
|
396
398
|
}
|
|
397
|
-
|
|
399
|
+
/**
|
|
400
|
+
* Get the system Python executable path.
|
|
401
|
+
* This function returns the absolute path to the system Python executable (e.g., /Users/penwa/miniconda3/envs/browser-use-temp/bin/python).
|
|
402
|
+
* It uses 'which python' (Unix) or 'where python' (Windows) to locate the executable.
|
|
403
|
+
* @returns {Promise<string | null>} The path to the Python executable, or null if not found.
|
|
404
|
+
*/
|
|
405
|
+
export async function getSystemPythonExecutablePath() {
|
|
406
|
+
const command = process.platform === 'win32' ? 'where python' : 'which python';
|
|
407
|
+
Logger.debug({
|
|
408
|
+
action: 'get_system_python_executable_path',
|
|
409
|
+
command
|
|
410
|
+
});
|
|
411
|
+
try {
|
|
412
|
+
const { stdout } = await execAsync(command);
|
|
413
|
+
// Use the first path found, trim whitespace
|
|
414
|
+
const pythonPath = stdout.split('\n')[0].trim();
|
|
415
|
+
if (pythonPath) {
|
|
416
|
+
Logger.debug({
|
|
417
|
+
action: 'get_system_python_executable_path_success',
|
|
418
|
+
pythonPath
|
|
419
|
+
});
|
|
420
|
+
return pythonPath;
|
|
421
|
+
}
|
|
422
|
+
Logger.debug('No Python executable found');
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
Logger.debug(`Could not find system python using "${command}": ${error}`);
|
|
427
|
+
return null;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
export async function getBrowserPath() {
|
|
398
431
|
const osType = getOSType();
|
|
399
432
|
Logger.debug({
|
|
400
433
|
action: 'get_system_browser_path',
|
|
@@ -471,4 +504,62 @@ export async function GetBrowserPath() {
|
|
|
471
504
|
throw error;
|
|
472
505
|
}
|
|
473
506
|
}
|
|
507
|
+
/**
|
|
508
|
+
* Get the global NPM path
|
|
509
|
+
* This function checks if NVM is installed and retrieves the global NPM path accordingly.
|
|
510
|
+
* If NVM is not installed, it falls back to the global NPM path.
|
|
511
|
+
* @returns The global NPM path as a string.
|
|
512
|
+
* @throws Error if the NPM path cannot be determined.
|
|
513
|
+
* */
|
|
514
|
+
export function getGlobalNPMPackagePath() {
|
|
515
|
+
const nvmHome = process.env.NVM_HOME;
|
|
516
|
+
if (nvmHome) {
|
|
517
|
+
try {
|
|
518
|
+
const nodeVersion = execSync('node -v').toString().trim();
|
|
519
|
+
const nvmNodePath = path.join(nvmHome, nodeVersion);
|
|
520
|
+
// Check if this path exists
|
|
521
|
+
try {
|
|
522
|
+
fsSync.accessSync(nvmNodePath);
|
|
523
|
+
return nvmNodePath;
|
|
524
|
+
}
|
|
525
|
+
catch (error) {
|
|
526
|
+
Logger.debug(`NVM controlled path doesn't exist: ${nvmNodePath}, will try global npm`);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
catch (error) {
|
|
530
|
+
Logger.debug(`Error determining Node version for NVM: ${error}, will use global npm`);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
const globalNpmPath = execSync('npm root -g').toString().trim();
|
|
534
|
+
return globalNpmPath;
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* Get the NPM executable path on the current platform (Windows, macOS, Linux).
|
|
538
|
+
* On Windows, uses PowerShell to locate npm. On macOS/Linux, uses 'which' to locate npm.
|
|
539
|
+
* Returns the directory containing the npm executable, or a platform-appropriate default if not found.
|
|
540
|
+
*/
|
|
541
|
+
export async function getNpmExecutablePath() {
|
|
542
|
+
try {
|
|
543
|
+
if (process.platform === 'win32') {
|
|
544
|
+
const { stdout } = await execAsync('powershell -Command "get-command npm | Select-Object -ExpandProperty Source"');
|
|
545
|
+
return stdout.trim().replace(/\\npm\.cmd$/, '');
|
|
546
|
+
}
|
|
547
|
+
else {
|
|
548
|
+
// macOS or Linux
|
|
549
|
+
const { stdout } = await execAsync('which npm');
|
|
550
|
+
// Remove the trailing '/npm' to get the directory
|
|
551
|
+
return stdout.trim().replace(/\/npm$/, '');
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
catch (error) {
|
|
555
|
+
Logger.error('Error getting npm path:', error);
|
|
556
|
+
if (process.platform === 'win32') {
|
|
557
|
+
return 'C:\\Program Files\\nodejs';
|
|
558
|
+
}
|
|
559
|
+
else {
|
|
560
|
+
// Common default for Unix systems
|
|
561
|
+
return '/usr/local/bin';
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
474
565
|
//# sourceMappingURL=osUtils.js.map
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
export declare function getPackageVersion():
|
|
1
|
+
export declare function getPackageVersion(): {
|
|
2
|
+
packageName: string;
|
|
3
|
+
packageVersion: string;
|
|
4
|
+
};
|
|
2
5
|
/**
|
|
3
6
|
* Utility functions for version comparison and management
|
|
4
7
|
*/
|
|
@@ -11,3 +14,19 @@ export declare function getPackageVersion(): string;
|
|
|
11
14
|
* a positive number if v1 > v2, 0 if equal)
|
|
12
15
|
*/
|
|
13
16
|
export declare function compareVersions(v1: string, v2: string): number;
|
|
17
|
+
/**
|
|
18
|
+
* Check if there's a newer version of the package available
|
|
19
|
+
*/
|
|
20
|
+
export declare function checkForUpdates(): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Retrieves the application version and information about available updates.
|
|
23
|
+
* @returns A promise that resolves to an object containing the current packageVersion and any availableUpdates.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getAppVersion(): Promise<{
|
|
26
|
+
name: string;
|
|
27
|
+
version: string;
|
|
28
|
+
availableUpdate?: {
|
|
29
|
+
latestVersion: string;
|
|
30
|
+
message: string;
|
|
31
|
+
};
|
|
32
|
+
}>;
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
+
import axios from 'axios';
|
|
5
|
+
import { Logger } from './logger.js'; // Assuming logger.js is in the same directory
|
|
6
|
+
// ANSI color codes
|
|
7
|
+
const COLORS = {
|
|
8
|
+
reset: '\x1b[0m',
|
|
9
|
+
yellow: '\x1b[33m'
|
|
10
|
+
};
|
|
11
|
+
const PACKAGE_NAME = 'imcp'; // Default package name
|
|
4
12
|
export function getPackageVersion() {
|
|
5
13
|
try {
|
|
6
14
|
// First try npm environment variable (available during npm scripts)
|
|
7
15
|
if (process.env.npm_package_version) {
|
|
8
|
-
return process.env.npm_package_version;
|
|
16
|
+
return { packageName: PACKAGE_NAME, packageVersion: process.env.npm_package_version };
|
|
9
17
|
}
|
|
10
18
|
// Fall back to reading package.json
|
|
11
19
|
// Get directory name of current module
|
|
@@ -16,15 +24,15 @@ export function getPackageVersion() {
|
|
|
16
24
|
const packagePath = path.join(currentDir, 'package.json');
|
|
17
25
|
if (fs.existsSync(packagePath)) {
|
|
18
26
|
const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
|
|
19
|
-
return packageJson.version;
|
|
27
|
+
return { packageName: PACKAGE_NAME, packageVersion: packageJson.version };
|
|
20
28
|
}
|
|
21
29
|
currentDir = path.join(currentDir, '..');
|
|
22
30
|
}
|
|
23
|
-
return 'unknown';
|
|
31
|
+
return { packageName: PACKAGE_NAME, packageVersion: 'unknown' };
|
|
24
32
|
}
|
|
25
33
|
catch (error) {
|
|
26
34
|
console.error('Failed to get package version:', error);
|
|
27
|
-
return 'unknown';
|
|
35
|
+
return { packageName: PACKAGE_NAME, packageVersion: 'unknown' };
|
|
28
36
|
}
|
|
29
37
|
}
|
|
30
38
|
/**
|
|
@@ -52,4 +60,43 @@ export function compareVersions(v1, v2) {
|
|
|
52
60
|
}
|
|
53
61
|
return 0;
|
|
54
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Check if there's a newer version of the package available
|
|
65
|
+
*/
|
|
66
|
+
export async function checkForUpdates() {
|
|
67
|
+
Logger.debug(`Checking for updates...`);
|
|
68
|
+
try {
|
|
69
|
+
const version = await getAppVersion();
|
|
70
|
+
if (version.availableUpdate) {
|
|
71
|
+
console.log(`${COLORS.yellow}Update available for ${version.name}: ${version.version} → ${version.availableUpdate.latestVersion}${COLORS.reset}`);
|
|
72
|
+
console.log(`${COLORS.yellow}Relaunch with \`npx -y ${version.name}@latest serve\` or update package with \`npm install -g ${version.name}@latest\`${COLORS.reset}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
// Log the npm error
|
|
77
|
+
Logger.debug(`Failed to check npm registry: ${error instanceof Error ? error.message : String(error)}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Retrieves the application version and information about available updates.
|
|
82
|
+
* @returns A promise that resolves to an object containing the current packageVersion and any availableUpdates.
|
|
83
|
+
*/
|
|
84
|
+
export async function getAppVersion() {
|
|
85
|
+
let availableUpdate = undefined;
|
|
86
|
+
const { packageName, packageVersion } = getPackageVersion();
|
|
87
|
+
// Check for updates from npm registry
|
|
88
|
+
try {
|
|
89
|
+
const npmResponse = await axios.get(`https://registry.npmjs.org/${packageName}`);
|
|
90
|
+
if (npmResponse.data && npmResponse.data['dist-tags'] && npmResponse.data['dist-tags'].latest) {
|
|
91
|
+
const latestVersion = npmResponse.data['dist-tags'].latest;
|
|
92
|
+
if (compareVersions(latestVersion, packageVersion) > 0) {
|
|
93
|
+
availableUpdate = { latestVersion, message: `New version (${latestVersion}) is available. Relaunch with \`npx -y ${packageName}@latest serve\`` };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (npmError) {
|
|
98
|
+
Logger.debug(`Failed to fetch latest version from npm for ${packageName}: ${npmError instanceof Error ? npmError.message : String(npmError)}`);
|
|
99
|
+
}
|
|
100
|
+
return { name: packageName, version: packageVersion, availableUpdate };
|
|
101
|
+
}
|
|
55
102
|
//# sourceMappingURL=versionUtils.js.map
|