imcp 0.0.3 → 0.0.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 +5 -6
- package/dist/cli/commands/install.js +2 -0
- package/dist/cli/commands/list.js +1 -0
- package/dist/cli/index.js +1 -2
- package/dist/core/ConfigurationLoader.d.ts +32 -0
- package/dist/core/ConfigurationLoader.js +213 -0
- package/dist/core/ConfigurationProvider.d.ts +2 -3
- package/dist/core/ConfigurationProvider.js +13 -182
- package/dist/core/InstallationService.d.ts +8 -0
- package/dist/core/InstallationService.js +124 -96
- package/dist/core/RequirementService.d.ts +1 -1
- package/dist/core/RequirementService.js +5 -9
- package/dist/core/constants.js +14 -1
- package/dist/core/installers/BaseInstaller.d.ts +5 -4
- package/dist/core/installers/BaseInstaller.js +17 -28
- package/dist/core/installers/ClientInstaller.js +159 -39
- package/dist/core/installers/CommandInstaller.d.ts +1 -0
- package/dist/core/installers/CommandInstaller.js +3 -0
- package/dist/core/installers/GeneralInstaller.d.ts +1 -0
- package/dist/core/installers/GeneralInstaller.js +3 -0
- package/dist/core/installers/InstallerFactory.d.ts +9 -7
- package/dist/core/installers/InstallerFactory.js +10 -8
- package/dist/core/installers/NpmInstaller.d.ts +1 -0
- package/dist/core/installers/NpmInstaller.js +3 -0
- package/dist/core/installers/PipInstaller.d.ts +6 -3
- package/dist/core/installers/PipInstaller.js +21 -8
- package/dist/core/installers/RequirementInstaller.d.ts +4 -3
- package/dist/core/installers/clients/ClientInstaller.d.ts +23 -0
- package/dist/core/installers/clients/ClientInstaller.js +573 -0
- package/dist/core/installers/clients/ExtensionInstaller.d.ts +26 -0
- package/dist/core/installers/clients/ExtensionInstaller.js +149 -0
- package/dist/core/installers/index.d.ts +8 -6
- package/dist/core/installers/index.js +8 -6
- package/dist/core/installers/requirements/BaseInstaller.d.ts +59 -0
- package/dist/core/installers/requirements/BaseInstaller.js +168 -0
- package/dist/core/installers/requirements/CommandInstaller.d.ts +37 -0
- package/dist/core/installers/requirements/CommandInstaller.js +173 -0
- package/dist/core/installers/requirements/GeneralInstaller.d.ts +33 -0
- package/dist/core/installers/requirements/GeneralInstaller.js +86 -0
- package/dist/core/installers/requirements/InstallerFactory.d.ts +54 -0
- package/dist/core/installers/requirements/InstallerFactory.js +97 -0
- package/dist/core/installers/requirements/NpmInstaller.d.ts +26 -0
- package/dist/core/installers/requirements/NpmInstaller.js +128 -0
- package/dist/core/installers/requirements/PipInstaller.d.ts +28 -0
- package/dist/core/installers/requirements/PipInstaller.js +128 -0
- package/{src/core/installers/RequirementInstaller.ts → dist/core/installers/requirements/RequirementInstaller.d.ts} +33 -38
- package/dist/core/installers/requirements/RequirementInstaller.js +3 -0
- package/dist/core/types.d.ts +4 -1
- package/dist/services/ServerService.js +1 -1
- package/dist/utils/clientUtils.d.ts +0 -6
- package/dist/utils/clientUtils.js +3 -2
- package/dist/utils/githubUtils.d.ts +11 -0
- package/dist/utils/githubUtils.js +88 -0
- package/dist/utils/osUtils.d.ts +17 -0
- package/dist/utils/osUtils.js +184 -0
- package/dist/web/public/css/modal.css +97 -3
- package/dist/web/public/index.html +21 -2
- package/dist/web/public/js/modal.js +177 -28
- package/dist/web/public/js/serverCategoryDetails.js +12 -10
- package/dist/web/public/js/serverCategoryList.js +20 -5
- package/dist/web/public/modal.html +27 -13
- package/dist/web/server.js +1 -1
- package/package.json +2 -1
- package/src/cli/commands/install.ts +4 -2
- package/src/cli/commands/list.ts +1 -0
- package/src/cli/index.ts +1 -1
- package/src/core/ConfigurationLoader.ts +251 -0
- package/src/core/ConfigurationProvider.ts +13 -195
- package/src/core/InstallationService.ts +140 -106
- package/src/core/RequirementService.ts +5 -10
- package/src/core/constants.ts +15 -1
- package/src/core/installers/{ClientInstaller.ts → clients/ClientInstaller.ts} +185 -46
- package/src/core/installers/clients/ExtensionInstaller.ts +162 -0
- package/src/core/installers/index.ts +9 -7
- package/src/core/installers/{BaseInstaller.ts → requirements/BaseInstaller.ts} +10 -118
- package/src/core/installers/{CommandInstaller.ts → requirements/CommandInstaller.ts} +7 -3
- package/src/core/installers/{GeneralInstaller.ts → requirements/GeneralInstaller.ts} +6 -2
- package/src/core/installers/{InstallerFactory.ts → requirements/InstallerFactory.ts} +11 -9
- package/src/core/installers/{NpmInstaller.ts → requirements/NpmInstaller.ts} +7 -4
- package/src/core/installers/{PipInstaller.ts → requirements/PipInstaller.ts} +26 -10
- package/src/core/installers/requirements/RequirementInstaller.ts +41 -0
- package/src/core/types.ts +4 -1
- package/src/services/ServerService.ts +1 -1
- package/src/utils/clientUtils.ts +4 -2
- package/src/utils/githubUtils.ts +103 -0
- package/src/utils/osUtils.ts +206 -15
- package/src/web/public/css/modal.css +97 -3
- package/src/web/public/index.html +21 -2
- package/src/web/public/js/modal.js +177 -28
- package/src/web/public/js/serverCategoryDetails.js +12 -10
- package/src/web/public/js/serverCategoryList.js +20 -5
- package/src/web/public/modal.html +27 -13
- package/src/web/server.ts +1 -1
|
@@ -4,8 +4,9 @@ import { exec } from 'child_process';
|
|
|
4
4
|
import util from 'util';
|
|
5
5
|
import { createInstallerFactory } from './installers/index.js';
|
|
6
6
|
import { SUPPORTED_CLIENTS } from './constants.js';
|
|
7
|
-
import { ClientInstaller } from './installers/ClientInstaller.js';
|
|
7
|
+
import { ClientInstaller } from './installers/clients/ClientInstaller.js';
|
|
8
8
|
import { ConfigurationProvider } from './ConfigurationProvider.js';
|
|
9
|
+
import { Logger } from '../utils/logger.js';
|
|
9
10
|
const execPromise = util.promisify(exec);
|
|
10
11
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
12
|
/**
|
|
@@ -54,94 +55,9 @@ export class InstallationService {
|
|
|
54
55
|
}
|
|
55
56
|
// Create new ClientInstaller instance for handling installation
|
|
56
57
|
const clientInstaller = new ClientInstaller(categoryName, serverName, clients);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
// Get feed configuration to get requirements
|
|
61
|
-
const feedConfig = await configProvider.getFeedConfiguration(categoryName);
|
|
62
|
-
if (!feedConfig) {
|
|
63
|
-
return {
|
|
64
|
-
success: false,
|
|
65
|
-
message: 'Feed configuration not found',
|
|
66
|
-
status: [{
|
|
67
|
-
status: 'failed',
|
|
68
|
-
type: 'install',
|
|
69
|
-
target: 'server',
|
|
70
|
-
message: 'Feed configuration not found'
|
|
71
|
-
}]
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
// Find server config
|
|
75
|
-
const serverConfig = feedConfig.mcpServers.find((s) => s.name === serverName);
|
|
76
|
-
if (!serverConfig?.dependencies?.requirements) {
|
|
77
|
-
return {
|
|
78
|
-
success: false,
|
|
79
|
-
message: 'Server configuration or requirements not found',
|
|
80
|
-
status: [{
|
|
81
|
-
status: 'failed',
|
|
82
|
-
type: 'install',
|
|
83
|
-
target: 'server',
|
|
84
|
-
message: 'Server configuration or requirements not found'
|
|
85
|
-
}]
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
// Install requirements asynchronously
|
|
89
|
-
for (const requirement of serverConfig.dependencies.requirements) {
|
|
90
|
-
// Create full RequirementConfig from dependency requirement
|
|
91
|
-
const feeds = await configProvider.getFeedConfiguration(categoryName);
|
|
92
|
-
const requirementConfig = feeds?.requirements?.find((r) => r.name === requirement.name) || {
|
|
93
|
-
name: requirement.name,
|
|
94
|
-
version: requirement.version,
|
|
95
|
-
type: 'npm' // Default to npm, can be enhanced to determine from requirement or config
|
|
96
|
-
};
|
|
97
|
-
const installer = this.installerFactory.getInstaller(requirementConfig);
|
|
98
|
-
if (!installer) {
|
|
99
|
-
await configProvider.updateRequirementStatus(categoryName, requirement.name, {
|
|
100
|
-
name: requirement.name,
|
|
101
|
-
type: requirementConfig.type,
|
|
102
|
-
installed: false,
|
|
103
|
-
error: `No installer found for requirement type: ${requirementConfig.type}`,
|
|
104
|
-
operationStatus: {
|
|
105
|
-
status: 'failed',
|
|
106
|
-
type: 'install',
|
|
107
|
-
target: 'requirement',
|
|
108
|
-
message: `No installer found for requirement type: ${requirementConfig.type}`,
|
|
109
|
-
operationId: this.generateOperationId()
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
// Create operation status for requirement
|
|
115
|
-
const operationStatus = {
|
|
116
|
-
status: 'pending',
|
|
117
|
-
type: 'install',
|
|
118
|
-
target: 'requirement',
|
|
119
|
-
message: `Installing requirement: ${requirement.name}`,
|
|
120
|
-
operationId: this.generateOperationId()
|
|
121
|
-
};
|
|
122
|
-
// Update requirement status
|
|
123
|
-
await configProvider.updateRequirementStatus(categoryName, requirement.name, {
|
|
124
|
-
name: requirement.name,
|
|
125
|
-
type: requirementConfig.type,
|
|
126
|
-
installed: false,
|
|
127
|
-
inProgress: true,
|
|
128
|
-
operationStatus
|
|
129
|
-
});
|
|
130
|
-
// Start async installation
|
|
131
|
-
installer.install(requirementConfig).then(async (installStatus) => {
|
|
132
|
-
const status = {
|
|
133
|
-
...installStatus,
|
|
134
|
-
operationStatus: {
|
|
135
|
-
status: installStatus.installed ? 'completed' : 'failed',
|
|
136
|
-
type: 'install',
|
|
137
|
-
target: 'requirement',
|
|
138
|
-
message: installStatus.installed ? `Requirement ${requirement.name} installed successfully` : `Failed to install ${requirement.name}`,
|
|
139
|
-
operationId: operationStatus.operationId
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
await configProvider.updateRequirementStatus(categoryName, requirement.name, status);
|
|
143
|
-
});
|
|
144
|
-
}
|
|
58
|
+
const requirementsResult = await this.checkAndInstallRequirements(categoryName, serverName, options);
|
|
59
|
+
if (requirementsResult) {
|
|
60
|
+
return requirementsResult;
|
|
145
61
|
}
|
|
146
62
|
// Process client installation regardless of requirements state
|
|
147
63
|
// Each client installer will check requirements before actual installation
|
|
@@ -191,9 +107,9 @@ export class InstallationService {
|
|
|
191
107
|
// Update requirement status to indicate update in progress
|
|
192
108
|
await configProvider.updateRequirementStatus(categoryName, reqToUpdate.name, {
|
|
193
109
|
...currentStatus,
|
|
194
|
-
name: reqToUpdate.name,
|
|
195
|
-
type: currentStatus.type || 'unknown',
|
|
196
|
-
installed: currentStatus.installed || false,
|
|
110
|
+
name: reqToUpdate.name,
|
|
111
|
+
type: currentStatus.type || 'unknown',
|
|
112
|
+
installed: currentStatus.installed || false,
|
|
197
113
|
inProgress: true,
|
|
198
114
|
operationStatus: {
|
|
199
115
|
status: 'in-progress',
|
|
@@ -212,9 +128,9 @@ export class InstallationService {
|
|
|
212
128
|
// Update requirement status
|
|
213
129
|
await configProvider.updateRequirementStatus(categoryName, reqToUpdate.name, {
|
|
214
130
|
...updatedStatus,
|
|
215
|
-
name: reqToUpdate.name,
|
|
216
|
-
type: updatedStatus.type || currentStatus.type || 'unknown',
|
|
217
|
-
installed: updatedStatus.installed,
|
|
131
|
+
name: reqToUpdate.name,
|
|
132
|
+
type: updatedStatus.type || currentStatus.type || 'unknown',
|
|
133
|
+
installed: updatedStatus.installed,
|
|
218
134
|
inProgress: false,
|
|
219
135
|
operationStatus: {
|
|
220
136
|
status: updatedStatus.installed ? 'completed' : 'failed',
|
|
@@ -224,7 +140,6 @@ export class InstallationService {
|
|
|
224
140
|
? `Successfully updated ${reqToUpdate.name} to version ${reqToUpdate.version}`
|
|
225
141
|
: `Failed to update ${reqToUpdate.name} to version ${reqToUpdate.version}`
|
|
226
142
|
},
|
|
227
|
-
// Clear availableUpdate if update was successful
|
|
228
143
|
availableUpdate: updatedStatus.installed ? undefined : currentStatus.availableUpdate
|
|
229
144
|
});
|
|
230
145
|
console.log(`Requirement ${reqToUpdate.name} updated to version ${reqToUpdate.version}`);
|
|
@@ -255,6 +170,119 @@ export class InstallationService {
|
|
|
255
170
|
await updateCheckTracker.endOperation(operationKey);
|
|
256
171
|
}
|
|
257
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Checks and installs requirements for a server if needed
|
|
175
|
+
* @param categoryName The category name
|
|
176
|
+
* @param serverName The server name
|
|
177
|
+
* @param options The installation options
|
|
178
|
+
* @returns A failure result if requirements check fails, null if requirements are satisfied
|
|
179
|
+
*/
|
|
180
|
+
async checkAndInstallRequirements(categoryName, serverName, options) {
|
|
181
|
+
const configProvider = ConfigurationProvider.getInstance();
|
|
182
|
+
// Get feed configuration to get requirements
|
|
183
|
+
const feedConfig = await configProvider.getFeedConfiguration(categoryName);
|
|
184
|
+
if (!feedConfig) {
|
|
185
|
+
return {
|
|
186
|
+
success: false,
|
|
187
|
+
message: 'Feed configuration not found',
|
|
188
|
+
status: [{
|
|
189
|
+
status: 'failed',
|
|
190
|
+
type: 'install',
|
|
191
|
+
target: 'server',
|
|
192
|
+
message: 'Feed configuration not found'
|
|
193
|
+
}]
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
// Find server config and verify requirements
|
|
197
|
+
const serverConfig = feedConfig.mcpServers.find((s) => s.name === serverName);
|
|
198
|
+
if (!serverConfig?.dependencies?.requirements) {
|
|
199
|
+
Logger.debug(`No requirements for ${serverName}`);
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
// Check all requirements installation status
|
|
203
|
+
const requirementStatuses = await Promise.all(serverConfig.dependencies.requirements.map(async (req) => {
|
|
204
|
+
const reqConfig = feedConfig.requirements?.find((r) => r.name === req.name) || {
|
|
205
|
+
name: req.name,
|
|
206
|
+
version: req.version,
|
|
207
|
+
type: 'npm'
|
|
208
|
+
};
|
|
209
|
+
return await this.installerFactory.checkInstallation(reqConfig, options);
|
|
210
|
+
}));
|
|
211
|
+
// If all requirements are installed and ready, no need to proceed with installation
|
|
212
|
+
if (requirementStatuses.every(status => status.installed)) {
|
|
213
|
+
// Check if requirements are ready via ConfigurationProvider
|
|
214
|
+
const requirementsReady = await configProvider.isRequirementsReady(categoryName, serverName);
|
|
215
|
+
// Update requirement status if not ready
|
|
216
|
+
if (!requirementsReady) {
|
|
217
|
+
for (const status of requirementStatuses) {
|
|
218
|
+
await configProvider.updateRequirementStatus(categoryName, status.name, status);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
// Sort requirements by order for installation
|
|
224
|
+
const sortedRequirements = [...serverConfig.dependencies.requirements].sort((a, b) => {
|
|
225
|
+
const orderA = a.order ?? Infinity;
|
|
226
|
+
const orderB = b.order ?? Infinity;
|
|
227
|
+
return orderA - orderB;
|
|
228
|
+
});
|
|
229
|
+
// Chain installations in sequence while keeping them non-blocking
|
|
230
|
+
await sortedRequirements.reduce((chain, requirement) => {
|
|
231
|
+
return chain.then(async () => {
|
|
232
|
+
const feeds = await configProvider.getFeedConfiguration(categoryName);
|
|
233
|
+
const requirementConfig = feeds?.requirements?.find((r) => r.name === requirement.name) || {
|
|
234
|
+
name: requirement.name,
|
|
235
|
+
version: requirement.version,
|
|
236
|
+
type: 'npm'
|
|
237
|
+
};
|
|
238
|
+
const installer = this.installerFactory.getInstaller(requirementConfig);
|
|
239
|
+
if (!installer) {
|
|
240
|
+
await configProvider.updateRequirementStatus(categoryName, requirement.name, {
|
|
241
|
+
name: requirement.name,
|
|
242
|
+
type: requirementConfig.type,
|
|
243
|
+
installed: false,
|
|
244
|
+
error: `No installer found for requirement type: ${requirementConfig.type}`,
|
|
245
|
+
operationStatus: {
|
|
246
|
+
status: 'failed',
|
|
247
|
+
type: 'install',
|
|
248
|
+
target: 'requirement',
|
|
249
|
+
message: `No installer found for requirement type: ${requirementConfig.type}`,
|
|
250
|
+
operationId: this.generateOperationId()
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
const operationStatus = {
|
|
256
|
+
status: 'pending',
|
|
257
|
+
type: 'install',
|
|
258
|
+
target: 'requirement',
|
|
259
|
+
message: `Installing requirement: ${requirement.name}`,
|
|
260
|
+
operationId: this.generateOperationId()
|
|
261
|
+
};
|
|
262
|
+
await configProvider.updateRequirementStatus(categoryName, requirement.name, {
|
|
263
|
+
name: requirement.name,
|
|
264
|
+
type: requirementConfig.type,
|
|
265
|
+
installed: false,
|
|
266
|
+
inProgress: true,
|
|
267
|
+
operationStatus
|
|
268
|
+
});
|
|
269
|
+
return installer.install(requirementConfig, options).then(async (installStatus) => {
|
|
270
|
+
const status = {
|
|
271
|
+
...installStatus,
|
|
272
|
+
operationStatus: {
|
|
273
|
+
status: installStatus.installed ? 'completed' : 'failed',
|
|
274
|
+
type: 'install',
|
|
275
|
+
target: 'requirement',
|
|
276
|
+
message: installStatus.installed ? `Requirement ${requirement.name} installed successfully` : `Failed to install ${requirement.name}`,
|
|
277
|
+
operationId: operationStatus.operationId
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
await configProvider.updateRequirementStatus(categoryName, requirement.name, status);
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
}, Promise.resolve());
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
258
286
|
}
|
|
259
287
|
// Export a singleton instance (optional)
|
|
260
288
|
// export const installationService = new InstallationService();
|
|
@@ -28,7 +28,7 @@ export declare class RequirementService {
|
|
|
28
28
|
* @param requirement The requirement to check for updates
|
|
29
29
|
* @returns Updated status with available updates information
|
|
30
30
|
*/
|
|
31
|
-
checkRequirementForUpdates(requirement: RequirementConfig): Promise<RequirementStatus>;
|
|
31
|
+
checkRequirementForUpdates(requirement: RequirementConfig, currentStatus: RequirementStatus): Promise<RequirementStatus>;
|
|
32
32
|
/**
|
|
33
33
|
* Update a requirement to a new version
|
|
34
34
|
* @param requirement The requirement configuration
|
|
@@ -45,21 +45,17 @@ export class RequirementService {
|
|
|
45
45
|
* @param requirement The requirement to check for updates
|
|
46
46
|
* @returns Updated status with available updates information
|
|
47
47
|
*/
|
|
48
|
-
async checkRequirementForUpdates(requirement) {
|
|
48
|
+
async checkRequirementForUpdates(requirement, currentStatus) {
|
|
49
49
|
// Validate requirement
|
|
50
50
|
this.validateRequirement(requirement);
|
|
51
51
|
// Get current status
|
|
52
|
-
const status = await this.checkRequirementStatus(requirement);
|
|
53
52
|
// Check for updates using the appropriate installer
|
|
54
53
|
const installer = this.installerFactory.getInstaller(requirement);
|
|
55
|
-
if (!installer) {
|
|
56
|
-
return
|
|
57
|
-
}
|
|
58
|
-
// If the installer supports update checking, use it
|
|
59
|
-
if ('checkForUpdates' in installer) {
|
|
60
|
-
return await installer.checkForUpdates(requirement, status);
|
|
54
|
+
if (!installer || !installer.supportCheckUpdates()) {
|
|
55
|
+
return currentStatus;
|
|
61
56
|
}
|
|
62
|
-
|
|
57
|
+
const status = await this.checkRequirementStatus(requirement);
|
|
58
|
+
return await installer.checkForUpdates(requirement, status);
|
|
63
59
|
}
|
|
64
60
|
/**
|
|
65
61
|
* Update a requirement to a new version
|
package/dist/core/constants.js
CHANGED
|
@@ -53,14 +53,27 @@ const CODE_INSIDER_STRORAGE_DIR = (() => {
|
|
|
53
53
|
*/
|
|
54
54
|
export const SUPPORTED_CLIENTS = {
|
|
55
55
|
'MSRooCode': {
|
|
56
|
+
extension: {
|
|
57
|
+
extensionId: 'microsoftai.ms-roo-cline',
|
|
58
|
+
leastVersion: '0.0.8',
|
|
59
|
+
repository: 'ai-microsoft/roo-cline',
|
|
60
|
+
assetName: 'ms-roo-cline-${version}.vsix',
|
|
61
|
+
private: true
|
|
62
|
+
},
|
|
56
63
|
codeSettingPath: path.join(CODE_STRORAGE_DIR, 'globalStorage', 'microsoftai.ms-roo-cline', 'settings', 'cline_mcp_settings.json'),
|
|
57
|
-
codeInsiderSettingPath: path.join(CODE_INSIDER_STRORAGE_DIR, 'globalStorage', 'microsoftai.ms-roo-
|
|
64
|
+
codeInsiderSettingPath: path.join(CODE_INSIDER_STRORAGE_DIR, 'globalStorage', 'microsoftai.ms-roo-cline', 'settings', 'cline_mcp_settings.json'),
|
|
58
65
|
},
|
|
59
66
|
'Cline': {
|
|
67
|
+
extension: {
|
|
68
|
+
extensionId: 'saoudrizwan.claude-dev',
|
|
69
|
+
},
|
|
60
70
|
codeSettingPath: path.join(CODE_STRORAGE_DIR, 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'),
|
|
61
71
|
codeInsiderSettingPath: path.join(CODE_INSIDER_STRORAGE_DIR, 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'),
|
|
62
72
|
},
|
|
63
73
|
'GithubCopilot': {
|
|
74
|
+
extension: {
|
|
75
|
+
extensionId: 'github.copilot',
|
|
76
|
+
},
|
|
64
77
|
codeSettingPath: path.join(CODE_STRORAGE_DIR, 'settings.json'),
|
|
65
78
|
codeInsiderSettingPath: path.join(CODE_INSIDER_STRORAGE_DIR, 'settings.json'),
|
|
66
79
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RequirementConfig, RequirementStatus, RegistryConfig } from '../types.js';
|
|
1
|
+
import { RequirementConfig, RequirementStatus, RegistryConfig, ServerInstallOptions } from '../types.js';
|
|
2
2
|
import { RequirementInstaller } from './RequirementInstaller.js';
|
|
3
3
|
/**
|
|
4
4
|
* Abstract base class with common functionality for all requirement installers
|
|
@@ -14,8 +14,9 @@ export declare abstract class BaseInstaller implements RequirementInstaller {
|
|
|
14
14
|
stderr: string;
|
|
15
15
|
}>);
|
|
16
16
|
abstract canHandle(requirement: RequirementConfig): boolean;
|
|
17
|
-
abstract
|
|
18
|
-
abstract
|
|
17
|
+
abstract supportCheckUpdates(): boolean;
|
|
18
|
+
abstract install(requirement: RequirementConfig, options?: ServerInstallOptions): Promise<RequirementStatus>;
|
|
19
|
+
abstract checkInstallation(requirement: RequirementConfig, options?: ServerInstallOptions): Promise<RequirementStatus>;
|
|
19
20
|
/**
|
|
20
21
|
* Check if updates are available for the requirement
|
|
21
22
|
* @param requirement The requirement to check
|
|
@@ -69,5 +70,5 @@ export declare abstract class BaseInstaller implements RequirementInstaller {
|
|
|
69
70
|
* @param packageName The name of the pip package
|
|
70
71
|
* @returns The latest version
|
|
71
72
|
*/
|
|
72
|
-
protected getPipLatestVersion(packageName: string): Promise<string>;
|
|
73
|
+
protected getPipLatestVersion(packageName: string, options?: ServerInstallOptions): Promise<string>;
|
|
73
74
|
}
|
|
@@ -96,31 +96,19 @@ export class BaseInstaller {
|
|
|
96
96
|
let resolvedAssetsName = assetsName || '';
|
|
97
97
|
const { stdout } = await this.execPromise(`gh release view --repo ${repository} --json tagName --jq .tagName`);
|
|
98
98
|
const latestTag = stdout.trim();
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
if (assetsName) {
|
|
116
|
-
resolvedAssetsName = assetsName.replace('${latest}', version).replace('${version}', version);
|
|
117
|
-
}
|
|
118
|
-
if (assetName) {
|
|
119
|
-
resolvedAssetName = assetName.replace('${latest}', version).replace('${version}', version);
|
|
120
|
-
}
|
|
121
|
-
Logger.debug(`Downloading ${requirement.name} from GitHub release ${repository} version ${version}`);
|
|
122
|
-
Logger.debug(`ResolvedAssetsName} ${resolvedAssetName}; ResolvedAsetName} ${resolvedAssetName}`);
|
|
123
|
-
}
|
|
99
|
+
let latestVersion = latestTag;
|
|
100
|
+
const tagWithVPrefix = latestVersion.startsWith('v');
|
|
101
|
+
if (tagWithVPrefix)
|
|
102
|
+
latestVersion = latestVersion.substring(1); // Remove 'v' prefix if present
|
|
103
|
+
version = version.includes("latest") ? latestVersion : version;
|
|
104
|
+
if (assetsName) {
|
|
105
|
+
resolvedAssetsName = assetsName.replace('${latest}', version).replace('${version}', version);
|
|
106
|
+
}
|
|
107
|
+
if (assetName) {
|
|
108
|
+
resolvedAssetName = assetName.replace('${latest}', version).replace('${version}', version);
|
|
109
|
+
}
|
|
110
|
+
Logger.debug(`Downloading ${requirement.name} from GitHub release ${repository} version ${version}`);
|
|
111
|
+
Logger.debug(`ResolvedAssetsName} ${resolvedAssetName}; ResolvedAsetName} ${resolvedAssetName}`);
|
|
124
112
|
const pattern = resolvedAssetsName ? resolvedAssetsName : resolvedAssetName;
|
|
125
113
|
Logger.debug(`Resolved pattern: ${pattern}`);
|
|
126
114
|
if (!pattern) {
|
|
@@ -129,7 +117,7 @@ export class BaseInstaller {
|
|
|
129
117
|
// Download the release asset
|
|
130
118
|
const downloadPath = path.join(this.downloadsDir, path.basename(pattern));
|
|
131
119
|
if (!await this.fileExists(downloadPath)) {
|
|
132
|
-
await this.execPromise(`gh release download ${
|
|
120
|
+
await this.execPromise(`gh release download ${tagWithVPrefix ? `v${version}` : version} --repo ${repository} --pattern "${pattern}" -O "${downloadPath}"`);
|
|
133
121
|
}
|
|
134
122
|
// Handle zip file extraction if the downloaded file is a zip
|
|
135
123
|
if (downloadPath.endsWith('.zip')) {
|
|
@@ -256,8 +244,9 @@ export class BaseInstaller {
|
|
|
256
244
|
* @param packageName The name of the pip package
|
|
257
245
|
* @returns The latest version
|
|
258
246
|
*/
|
|
259
|
-
async getPipLatestVersion(packageName) {
|
|
260
|
-
const
|
|
247
|
+
async getPipLatestVersion(packageName, options) {
|
|
248
|
+
const pythonCmd = options?.settings?.pythonEnv || 'python';
|
|
249
|
+
const { stdout } = await this.execPromise(`${pythonCmd} -m pip index versions ${packageName} --pre=0 | grep -oP "(?<=Latest:\\s)[^\\s]+" | head -1`);
|
|
261
250
|
return stdout.trim();
|
|
262
251
|
}
|
|
263
252
|
}
|