@mearl/setup 2.21.0 → 3.0.0-beta.0
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/LICENSE +201 -0
- package/README.md +59 -59
- package/dist/browserExtension.d.ts +2 -2
- package/dist/browserExtension.js +25 -19
- package/dist/cli.d.ts +8 -3
- package/dist/cli.js +74 -17
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/lifecycle.d.ts +11 -4
- package/dist/lifecycle.js +48 -15
- package/dist/managedPlugins.d.ts +21 -0
- package/dist/managedPlugins.js +76 -0
- package/dist/npmRegistry.d.ts +1 -1
- package/dist/npmRegistry.js +4 -16
- package/dist/plugin.d.ts +13 -3
- package/dist/plugin.js +106 -44
- package/dist/preset.d.ts +94 -0
- package/dist/preset.js +275 -0
- package/dist/presetBrowserTransfer.d.ts +11 -0
- package/dist/presetBrowserTransfer.js +72 -0
- package/dist/presetInstallationLease.d.ts +6 -0
- package/dist/presetInstallationLease.js +66 -0
- package/dist/presetStore.d.ts +48 -0
- package/dist/presetStore.js +252 -0
- package/dist/presetUpgrade.d.ts +13 -0
- package/dist/presetUpgrade.js +42 -0
- package/dist/provider.d.ts +2 -0
- package/dist/provider.js +24 -2
- package/dist/runtimeCleanup.js +1 -8
- package/dist/setupVersion.d.ts +2 -0
- package/dist/setupVersion.js +4 -0
- package/dist/skillSources.d.ts +43 -0
- package/dist/skillSources.js +247 -0
- package/dist/skills.d.ts +45 -0
- package/dist/skills.js +213 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +6 -0
- package/package.json +22 -10
- package/dist/aliSkills.d.ts +0 -32
- package/dist/aliSkills.js +0 -212
- package/dist/internalPlugins.d.ts +0 -26
- package/dist/internalPlugins.js +0 -197
package/dist/cli.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { createRequire } from 'node:module';
|
|
3
2
|
import { Command, CommanderError } from 'commander';
|
|
4
3
|
import { installMearlBrowserExtension, isUnsupportedCdpMethodError } from './browserExtension.js';
|
|
5
4
|
import { runMearlLifecycle } from './lifecycle.js';
|
|
6
5
|
import { isMearlReleaseLine } from './version.js';
|
|
7
6
|
import { ensureOfficialPlugin, installPlugins, setupPlugin, uninstallPlugin } from './plugin.js';
|
|
8
7
|
import { installProviderPackage, uninstallProviderPackage, updateProviderPackage, } from './provider.js';
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
import { runPresetCommand } from './preset.js';
|
|
9
|
+
import { prepareSetupPreset } from './presetUpgrade.js';
|
|
10
|
+
import { SETUP_VERSION, SETUP_COMMAND } from './setupVersion.js';
|
|
11
|
+
export { SETUP_VERSION } from './setupVersion.js';
|
|
11
12
|
const baseParsedArgs = () => ({
|
|
12
13
|
help: false,
|
|
13
14
|
skipSkill: false,
|
|
@@ -24,6 +25,13 @@ function commanderError(error) {
|
|
|
24
25
|
return new Error(message);
|
|
25
26
|
}
|
|
26
27
|
export function parseSetupArgs(argv) {
|
|
28
|
+
if (argv[0] === 'preset') {
|
|
29
|
+
if (argv[1] === 'apply' && argv.length === 3 && argv[2])
|
|
30
|
+
return { ...baseParsedArgs(), operation: 'preset', presetCommand: 'apply', presetSource: argv[2] };
|
|
31
|
+
if ((argv[1] === 'update' || argv[1] === 'status') && argv.length === 2)
|
|
32
|
+
return { ...baseParsedArgs(), operation: 'preset', presetCommand: argv[1] };
|
|
33
|
+
throw new Error('preset requires apply <source-url-or-path>, update, or status');
|
|
34
|
+
}
|
|
27
35
|
if (argv[0] === 'provider') {
|
|
28
36
|
const command = argv[1];
|
|
29
37
|
if ((command === 'install' || command === 'update' || command === 'uninstall') &&
|
|
@@ -83,6 +91,7 @@ export function parseSetupArgs(argv) {
|
|
|
83
91
|
.option('--mcp')
|
|
84
92
|
.option('--target-line <major.minor.x>')
|
|
85
93
|
.option('--skip-skill')
|
|
94
|
+
.option('--preset <source>')
|
|
86
95
|
.option('-y, --yes')
|
|
87
96
|
.option('--non-interactive');
|
|
88
97
|
if (operation === 'uninstall')
|
|
@@ -95,6 +104,10 @@ export function parseSetupArgs(argv) {
|
|
|
95
104
|
if (options.targetLine && !isMearlReleaseLine(options.targetLine)) {
|
|
96
105
|
throw new Error('--target-line requires a valid Mearl release line such as 2.3.x');
|
|
97
106
|
}
|
|
107
|
+
if (operation === 'uninstall' && options.preset)
|
|
108
|
+
throw new Error('--preset is not available for uninstall');
|
|
109
|
+
if (options.preset !== undefined && !options.preset.trim())
|
|
110
|
+
throw new Error('--preset requires a source');
|
|
98
111
|
if (operation === 'uninstall' && options.targetLine) {
|
|
99
112
|
throw new Error('--target-line is not available for uninstall');
|
|
100
113
|
}
|
|
@@ -115,6 +128,7 @@ export function parseSetupArgs(argv) {
|
|
|
115
128
|
...(options.full ? { full: true } : {}),
|
|
116
129
|
skipSkill: options.skipSkill === true,
|
|
117
130
|
targetLine: options.targetLine,
|
|
131
|
+
...(options.preset ? { presetSource: options.preset } : {}),
|
|
118
132
|
yes: options.yes === true || options.nonInteractive === true,
|
|
119
133
|
};
|
|
120
134
|
});
|
|
@@ -171,6 +185,9 @@ Environment commands:
|
|
|
171
185
|
uninstall [options] Uninstall detected or selected environments
|
|
172
186
|
|
|
173
187
|
Integration commands:
|
|
188
|
+
preset apply <source> Apply a preset, synchronize hosts and install declared components
|
|
189
|
+
preset update Update the selected preset, preserving user overrides
|
|
190
|
+
preset status Report actual readiness (exit 3 when synchronization is pending)
|
|
174
191
|
plugin install <arguments...> Install Skills and register their CLI plugins
|
|
175
192
|
plugin uninstall <name> Uninstall one CLI plugin
|
|
176
193
|
plugin [name] <path> Register an existing plugin; name overrides metadata
|
|
@@ -187,6 +204,7 @@ Environment options:
|
|
|
187
204
|
--qoder-cloud Manage cloud packages in Qoder pairing mode
|
|
188
205
|
--mcp Manage @mearl/mcp-server and its configuration
|
|
189
206
|
--target-line <major.minor.x> Use the latest packages in one release line
|
|
207
|
+
--preset <source> Apply a preset after installing or updating the environment
|
|
190
208
|
--skip-skill Keep the independently managed Mearl Skill unchanged
|
|
191
209
|
|
|
192
210
|
Uninstall options:
|
|
@@ -209,9 +227,27 @@ Examples:
|
|
|
209
227
|
npx @mearl/setup update
|
|
210
228
|
npx @mearl/setup uninstall --full
|
|
211
229
|
npx @mearl/setup plugin uninstall yuque
|
|
212
|
-
npx @mearl/setup provider install @
|
|
230
|
+
npx @mearl/setup provider install @example/mearl-provider-brow
|
|
213
231
|
npx @mearl/setup extension --full`;
|
|
214
|
-
console.log(output);
|
|
232
|
+
console.log(output.replaceAll('npx @mearl/setup', SETUP_COMMAND));
|
|
233
|
+
}
|
|
234
|
+
async function runSetupLifecycle(options, dependencies) {
|
|
235
|
+
let preset;
|
|
236
|
+
const callback = options.operation === 'uninstall' ? undefined : { onPresetStatus: (status) => { preset = status; } };
|
|
237
|
+
const lifecycle = dependencies.runLifecycle ?? runMearlLifecycle;
|
|
238
|
+
const ok = callback ? await lifecycle(options, callback) : await lifecycle(options);
|
|
239
|
+
if (!ok)
|
|
240
|
+
return 1;
|
|
241
|
+
if (!preset) {
|
|
242
|
+
if (options.presetSource)
|
|
243
|
+
throw new Error('Preset preparation did not complete');
|
|
244
|
+
return 0;
|
|
245
|
+
}
|
|
246
|
+
const actual = await (dependencies.runPreset ?? runPresetCommand)('status');
|
|
247
|
+
if (actual.revision !== preset.revision)
|
|
248
|
+
throw new Error('The selected preset changed while setup was running');
|
|
249
|
+
console.log(JSON.stringify(actual, null, 2));
|
|
250
|
+
return actual.ready ? 0 : 3;
|
|
215
251
|
}
|
|
216
252
|
export async function main(argv = process.argv.slice(2), interactiveTerminal = process.stdin.isTTY === true && process.stdout.isTTY === true, dependencies = {}) {
|
|
217
253
|
let parsed;
|
|
@@ -220,7 +256,7 @@ export async function main(argv = process.argv.slice(2), interactiveTerminal = p
|
|
|
220
256
|
}
|
|
221
257
|
catch (error) {
|
|
222
258
|
console.error(error instanceof Error ? error.message : String(error));
|
|
223
|
-
console.error(
|
|
259
|
+
console.error(`Run "${SETUP_COMMAND} --help" for usage.`);
|
|
224
260
|
return 2;
|
|
225
261
|
}
|
|
226
262
|
if (parsed.help) {
|
|
@@ -231,6 +267,17 @@ export async function main(argv = process.argv.slice(2), interactiveTerminal = p
|
|
|
231
267
|
console.log(SETUP_VERSION);
|
|
232
268
|
return 0;
|
|
233
269
|
}
|
|
270
|
+
if (parsed.operation === 'preset') {
|
|
271
|
+
try {
|
|
272
|
+
const result = await (dependencies.runPreset ?? runPresetCommand)(parsed.presetCommand, parsed.presetSource);
|
|
273
|
+
console.log(JSON.stringify(result, null, 2));
|
|
274
|
+
return result.ready ? 0 : 3;
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
278
|
+
return 1;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
234
281
|
if (parsed.operation === 'plugin') {
|
|
235
282
|
try {
|
|
236
283
|
if (parsed.pluginInstallArgs) {
|
|
@@ -250,8 +297,8 @@ export async function main(argv = process.argv.slice(2), interactiveTerminal = p
|
|
|
250
297
|
}
|
|
251
298
|
else if (result.skillName) {
|
|
252
299
|
console.error(result.entryMissing
|
|
253
|
-
? `Plugin ${parsed.pluginUninstallName} had a missing entry;
|
|
254
|
-
: `Plugin ${parsed.pluginUninstallName} uninstalled with
|
|
300
|
+
? `Plugin ${parsed.pluginUninstallName} had a missing entry; skills cleanup completed for ${result.skillName}.`
|
|
301
|
+
: `Plugin ${parsed.pluginUninstallName} uninstalled with skills skill ${result.skillName}.`);
|
|
255
302
|
if (result.unregisteredNames.length > 1) {
|
|
256
303
|
console.error(`Removed registrations: ${result.unregisteredNames.join(', ')}`);
|
|
257
304
|
}
|
|
@@ -302,6 +349,15 @@ export async function main(argv = process.argv.slice(2), interactiveTerminal = p
|
|
|
302
349
|
console.error('Non-interactive input detected. Re-run with --yes or --non-interactive.');
|
|
303
350
|
return 2;
|
|
304
351
|
}
|
|
352
|
+
if (parsed.full) {
|
|
353
|
+
try {
|
|
354
|
+
await (dependencies.preparePreset ?? prepareSetupPreset)({});
|
|
355
|
+
}
|
|
356
|
+
catch (error) {
|
|
357
|
+
console.error(`Preset preparation: ${error instanceof Error ? error.message : String(error)}`);
|
|
358
|
+
return 1;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
305
361
|
let extensionInstalled = false;
|
|
306
362
|
let extensionFailureIsTerminal = false;
|
|
307
363
|
try {
|
|
@@ -325,11 +381,11 @@ export async function main(argv = process.argv.slice(2), interactiveTerminal = p
|
|
|
325
381
|
if (result.cdpError) {
|
|
326
382
|
console.error(`CDP installation failed: ${result.cdpError}`);
|
|
327
383
|
if (isUnsupportedCdpMethodError(result.cdpError)) {
|
|
328
|
-
console.error(
|
|
384
|
+
console.error(`This Chrome version does not support installing extensions through CDP. Update Chrome to version 145 or later, then rerun: ${SETUP_COMMAND} extension`);
|
|
329
385
|
extensionFailureIsTerminal = true;
|
|
330
386
|
}
|
|
331
387
|
else {
|
|
332
|
-
console.error(
|
|
388
|
+
console.error(`Open chrome://inspect/#remote-debugging, enable remote debugging, approve the connection, then rerun: ${SETUP_COMMAND} extension`);
|
|
333
389
|
extensionFailureIsTerminal = parsed.yes;
|
|
334
390
|
}
|
|
335
391
|
}
|
|
@@ -340,26 +396,26 @@ export async function main(argv = process.argv.slice(2), interactiveTerminal = p
|
|
|
340
396
|
}
|
|
341
397
|
if (!parsed.full || extensionFailureIsTerminal)
|
|
342
398
|
return extensionInstalled ? 0 : 1;
|
|
343
|
-
let
|
|
399
|
+
let localStatus = 1;
|
|
344
400
|
try {
|
|
345
|
-
|
|
401
|
+
localStatus = await runSetupLifecycle({
|
|
346
402
|
operation: 'install',
|
|
347
403
|
profiles: ['local'],
|
|
348
404
|
skipSkill: false,
|
|
349
405
|
yes: parsed.yes,
|
|
350
|
-
});
|
|
406
|
+
}, dependencies);
|
|
351
407
|
}
|
|
352
408
|
catch (error) {
|
|
353
409
|
console.error(error instanceof Error ? error.message : String(error));
|
|
354
410
|
}
|
|
355
|
-
return extensionInstalled
|
|
411
|
+
return extensionInstalled ? localStatus : 1;
|
|
356
412
|
}
|
|
357
413
|
if (!interactiveTerminal && !parsed.yes && parsed.operation !== 'update') {
|
|
358
414
|
console.error('Non-interactive input detected. Re-run with --yes or --non-interactive.');
|
|
359
415
|
return 2;
|
|
360
416
|
}
|
|
361
417
|
try {
|
|
362
|
-
const
|
|
418
|
+
const options = {
|
|
363
419
|
operation: parsed.operation,
|
|
364
420
|
profiles: parsed.profiles,
|
|
365
421
|
cloudMode: parsed.cloudMode,
|
|
@@ -367,8 +423,9 @@ export async function main(argv = process.argv.slice(2), interactiveTerminal = p
|
|
|
367
423
|
skipSkill: parsed.skipSkill,
|
|
368
424
|
targetLine: parsed.targetLine,
|
|
369
425
|
yes: parsed.yes,
|
|
370
|
-
|
|
371
|
-
|
|
426
|
+
...(parsed.presetSource ? { presetSource: parsed.presetSource } : {}),
|
|
427
|
+
};
|
|
428
|
+
return await runSetupLifecycle(options, dependencies);
|
|
372
429
|
}
|
|
373
430
|
catch (error) {
|
|
374
431
|
console.error(error instanceof Error ? error.message : String(error));
|
package/dist/index.d.ts
CHANGED
|
@@ -7,8 +7,10 @@ export type { MearlLifecycleDependencies, MearlLifecycleOperation, MearlLifecycl
|
|
|
7
7
|
export { MEARL_PROFILES, detectMearlProfiles } from './profiles.js';
|
|
8
8
|
export type { DetectedMearlProfiles, MearlProfile, MearlProfileConfig } from './profiles.js';
|
|
9
9
|
export { MEARL_NATIVE_HOST_NAMES, resolveNativeHostDirectory, uninstallNativeHostArtifacts, } from './nativeHost.js';
|
|
10
|
+
export { PresetInstaller, PresetInstallationStore, createNodePresetLoader, runPresetCommand } from './preset.js';
|
|
11
|
+
export type { PresetInstallReceipt, PresetInstallStatus, PresetInstallerOptions, PresetApplyOptions, StagedPresetInstallation, PresetHostTarget, PresetHostStatus, PresetBrowserHostStatus, PresetComponentHostStatus, PresetComponentStatus } from './preset.js';
|
|
10
12
|
export { compareMearlReleaseLines, compareMearlReleaseVersions, isMearlReleaseLine, isMearlReleaseVersion, isMearlReleaseVersionInLine, mearlReleaseLineForVersion, parseMearlReleaseLine, parseMearlReleaseVersion, } from './version.js';
|
|
11
13
|
export type { MearlReleaseLine, MearlReleaseVersion } from './version.js';
|
|
12
|
-
export { installProviderPackage, parseProviderPackageSpec, uninstallProviderPackage, updateProviderPackage, } from './provider.js';
|
|
14
|
+
export { installProviderPackage, inspectProviderPackage, parseProviderPackageSpec, uninstallProviderPackage, updateProviderPackage, } from './provider.js';
|
|
13
15
|
export type { ProviderSetupDependencies, ProviderSetupResult } from './provider.js';
|
|
14
16
|
export type { NativeHostCleanupDependencies, NativeHostCleanupOptions, NativeHostIntegrationMode, } from './nativeHost.js';
|
package/dist/index.js
CHANGED
|
@@ -3,5 +3,6 @@ export { BrowserExtensionConflictError, extensionArchiveUrl, fetchBrowserExtensi
|
|
|
3
3
|
export { runMearlLifecycle } from './lifecycle.js';
|
|
4
4
|
export { MEARL_PROFILES, detectMearlProfiles } from './profiles.js';
|
|
5
5
|
export { MEARL_NATIVE_HOST_NAMES, resolveNativeHostDirectory, uninstallNativeHostArtifacts, } from './nativeHost.js';
|
|
6
|
+
export { PresetInstaller, PresetInstallationStore, createNodePresetLoader, runPresetCommand } from './preset.js';
|
|
6
7
|
export { compareMearlReleaseLines, compareMearlReleaseVersions, isMearlReleaseLine, isMearlReleaseVersion, isMearlReleaseVersionInLine, mearlReleaseLineForVersion, parseMearlReleaseLine, parseMearlReleaseVersion, } from './version.js';
|
|
7
|
-
export { installProviderPackage, parseProviderPackageSpec, uninstallProviderPackage, updateProviderPackage, } from './provider.js';
|
|
8
|
+
export { installProviderPackage, inspectProviderPackage, parseProviderPackageSpec, uninstallProviderPackage, updateProviderPackage, } from './provider.js';
|
package/dist/lifecycle.d.ts
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { listPluginNames } from '@mearl/client/plugin';
|
|
2
2
|
import { listInstalledProviders } from '@mearl/provider/host';
|
|
3
|
-
import { runGlobalMearlSkillOperation } from './
|
|
3
|
+
import { runGlobalMearlSkillOperation } from './skills.js';
|
|
4
4
|
import { detectGlobalPackage, type PackageManagerInstallation, type PackageDetectionOptions } from './packageManager.js';
|
|
5
5
|
import { type DetectedMearlProfiles, type MearlProfile } from './profiles.js';
|
|
6
6
|
import { uninstallNativeHostArtifacts } from './nativeHost.js';
|
|
7
7
|
import { type CommandRunner } from '@mearl/daemon-core';
|
|
8
|
-
import {
|
|
8
|
+
import { installManagedPlugins, uninstallManagedPlugins } from './managedPlugins.js';
|
|
9
9
|
import { uninstallPlugin } from './plugin.js';
|
|
10
10
|
import { uninstallProviderPackage } from './provider.js';
|
|
11
11
|
import { cleanupUninstalledRuntime } from './runtimeCleanup.js';
|
|
12
|
+
import { prepareSetupPreset } from './presetUpgrade.js';
|
|
13
|
+
import type { PresetInstallStatus } from './preset.js';
|
|
12
14
|
export type MearlLifecycleOperation = 'install' | 'update' | 'uninstall';
|
|
13
15
|
export interface MearlLifecycleOptions {
|
|
16
|
+
presetSource?: string;
|
|
14
17
|
operation: MearlLifecycleOperation;
|
|
15
18
|
cloudMode?: 'websocket' | 'qoder';
|
|
16
19
|
/** Uninstall every registered CLI plugin and Provider in addition to selected environments. */
|
|
@@ -24,19 +27,23 @@ export interface MearlLifecycleOptions {
|
|
|
24
27
|
env?: NodeJS.ProcessEnv;
|
|
25
28
|
}
|
|
26
29
|
export interface MearlLifecycleDependencies {
|
|
30
|
+
preparePreset?: typeof prepareSetupPreset;
|
|
31
|
+
onPresetStatus?: (status: PresetInstallStatus) => void;
|
|
32
|
+
/** Prepare the selected manager after packages are usable and before Skill operations. */
|
|
33
|
+
prepareSkills?: () => Promise<void>;
|
|
27
34
|
cleanupRuntime?: typeof cleanupUninstalledRuntime;
|
|
28
35
|
cleanupNativeHost?: typeof uninstallNativeHostArtifacts;
|
|
29
36
|
confirm?: (message: string) => Promise<boolean>;
|
|
30
37
|
detectPackage?: typeof detectGlobalPackage;
|
|
31
38
|
detectProfiles?: (env: NodeJS.ProcessEnv, options?: Pick<PackageDetectionOptions, 'includeLinked'>) => DetectedMearlProfiles;
|
|
32
39
|
existsSync?: (filePath: string) => boolean;
|
|
33
|
-
|
|
40
|
+
installManagedPlugins?: typeof installManagedPlugins;
|
|
34
41
|
listPlugins?: typeof listPluginNames;
|
|
35
42
|
listProviders?: typeof listInstalledProviders;
|
|
36
43
|
resolveInvokingManager?: (env: NodeJS.ProcessEnv) => PackageManagerInstallation;
|
|
37
44
|
runCommand?: CommandRunner;
|
|
38
45
|
runSkillOperation?: typeof runGlobalMearlSkillOperation;
|
|
39
|
-
|
|
46
|
+
uninstallManagedPlugins?: typeof uninstallManagedPlugins;
|
|
40
47
|
uninstallPlugin?: typeof uninstallPlugin;
|
|
41
48
|
uninstallProvider?: typeof uninstallProviderPackage;
|
|
42
49
|
writeLine?: (line: string) => void;
|
package/dist/lifecycle.js
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
|
+
import { SETUP_VERSION } from './setupVersion.js';
|
|
1
2
|
import fs from 'node:fs';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { createInterface } from 'node:readline/promises';
|
|
4
5
|
import { stdin as input, stdout as output } from 'node:process';
|
|
5
6
|
import { listPluginNames } from '@mearl/client/plugin';
|
|
6
7
|
import { listInstalledProviders } from '@mearl/provider/host';
|
|
7
|
-
import { runGlobalMearlSkillOperation } from './
|
|
8
|
+
import { runGlobalMearlSkillOperation } from './skills.js';
|
|
8
9
|
import { buildGlobalPackageCommand, detectGlobalPackage, resolveInvokingPackageManager, resolvePackageManagerInstallation, } from './packageManager.js';
|
|
9
10
|
import { MEARL_PROFILES, detectMearlProfiles, } from './profiles.js';
|
|
10
11
|
import { uninstallNativeHostArtifacts } from './nativeHost.js';
|
|
11
12
|
import { executableNames, prependCommandPath, runCommand, } from '@mearl/daemon-core';
|
|
12
|
-
import { isMearlReleaseLine } from './version.js';
|
|
13
|
-
import {
|
|
13
|
+
import { isMearlReleaseLine, mearlPackageSelector } from './version.js';
|
|
14
|
+
import { installManagedPlugins, uninstallManagedPlugins, } from './managedPlugins.js';
|
|
14
15
|
import { uninstallPlugin } from './plugin.js';
|
|
15
16
|
import { uninstallProviderPackage } from './provider.js';
|
|
16
17
|
import { packageRegistryEnvironment } from './npmRegistry.js';
|
|
17
18
|
import { cleanupUninstalledRuntime } from './runtimeCleanup.js';
|
|
19
|
+
import { prepareSetupPreset } from './presetUpgrade.js';
|
|
18
20
|
const LEGACY_CLOUD_CLIENT = '@mearl/cloud-client';
|
|
19
21
|
const UNIFIED_CLIENT = '@mearl/client';
|
|
20
22
|
const PROFILE_ORDER = ['local', 'cloud', 'mcp'];
|
|
@@ -273,6 +275,29 @@ export async function runMearlLifecycle(options, dependencies = {}) {
|
|
|
273
275
|
if (autoUpdateClient && lifecycleSelected.length === 0) {
|
|
274
276
|
writeLine('update targets: client CLI');
|
|
275
277
|
}
|
|
278
|
+
const selectedUsesClient = autoUpdateClient !== null ||
|
|
279
|
+
lifecycleSelected.some(profile => CLIENT_PROFILES.includes(profile));
|
|
280
|
+
const detectedClientCandidate = selectedUsesClient && !autoUpdateClient
|
|
281
|
+
? detectPackage(UNIFIED_CLIENT, ['mearl'], packageDetectionOptions)
|
|
282
|
+
: null;
|
|
283
|
+
const detectedClient = detectedClientCandidate?.packageName === UNIFIED_CLIENT ? detectedClientCandidate : null;
|
|
284
|
+
let stagedPreset;
|
|
285
|
+
if (options.operation !== 'uninstall' && (options.presetSource || !options.targetLine || Number(options.targetLine.split('.')[0]) >= 3) && !dependencies.prepareSkills) {
|
|
286
|
+
try {
|
|
287
|
+
stagedPreset = await (dependencies.preparePreset ?? prepareSetupPreset)({
|
|
288
|
+
source: options.presetSource, env,
|
|
289
|
+
installed: [
|
|
290
|
+
...lifecycleSelected.flatMap(profile => detected.get(profile) ? [detected.get(profile)] : []),
|
|
291
|
+
...(detectedClient ? [detectedClient] : []),
|
|
292
|
+
...(autoUpdateClient && env.MEARL_AUTO_UPDATE_CLIENT_ROOT ? [{ packageName: UNIFIED_CLIENT, packageRoot: env.MEARL_AUTO_UPDATE_CLIENT_ROOT }] : []),
|
|
293
|
+
],
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
writeLine(`Preset preparation: ${error instanceof Error ? error.message : String(error)}`);
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
276
301
|
let packagesOk = true;
|
|
277
302
|
if (lifecycleSelected.includes('cloud')) {
|
|
278
303
|
const legacyCloudClient = detectPackage(LEGACY_CLOUD_CLIENT, ['mearl-cloud'], packageDetectionOptions);
|
|
@@ -290,12 +315,6 @@ export async function runMearlLifecycle(options, dependencies = {}) {
|
|
|
290
315
|
}
|
|
291
316
|
}
|
|
292
317
|
}
|
|
293
|
-
const selectedUsesClient = autoUpdateClient !== null ||
|
|
294
|
-
lifecycleSelected.some(profile => CLIENT_PROFILES.includes(profile));
|
|
295
|
-
const detectedClientCandidate = selectedUsesClient && !autoUpdateClient
|
|
296
|
-
? detectPackage(UNIFIED_CLIENT, ['mearl'], packageDetectionOptions)
|
|
297
|
-
: null;
|
|
298
|
-
const detectedClient = detectedClientCandidate?.packageName === UNIFIED_CLIENT ? detectedClientCandidate : null;
|
|
299
318
|
const remainingClientProfiles = selectedUsesClient && options.operation === 'uninstall'
|
|
300
319
|
? CLIENT_PROFILES.filter(profile => detected.has(profile) && !lifecycleSelected.includes(profile))
|
|
301
320
|
: [];
|
|
@@ -305,7 +324,7 @@ export async function runMearlLifecycle(options, dependencies = {}) {
|
|
|
305
324
|
detected.get('local') ??
|
|
306
325
|
detected.get('cloud') ??
|
|
307
326
|
resolveInvokingManager(env);
|
|
308
|
-
const sharedClient = await runPackageOperation(clientInstallation, options.operation, [UNIFIED_CLIENT], options.targetLine, runner, env, 'Packages (shared client)', writeLine);
|
|
327
|
+
const sharedClient = await runPackageOperation(clientInstallation, options.operation, [UNIFIED_CLIENT], mearlPackageSelector(SETUP_VERSION, options.targetLine), runner, env, 'Packages (shared client)', writeLine);
|
|
309
328
|
if (!sharedClient.ok) {
|
|
310
329
|
writeLine('Mearl setup incomplete. Review the messages above.');
|
|
311
330
|
return false;
|
|
@@ -345,7 +364,7 @@ export async function runMearlLifecycle(options, dependencies = {}) {
|
|
|
345
364
|
if (packages.length === 0) {
|
|
346
365
|
continue;
|
|
347
366
|
}
|
|
348
|
-
const packageResult = await runPackageOperation(installation, packageOperation, packages, options.targetLine, runner, env, `Packages (${profile})`, writeLine);
|
|
367
|
+
const packageResult = await runPackageOperation(installation, packageOperation, packages, mearlPackageSelector(SETUP_VERSION, options.targetLine), runner, env, `Packages (${profile})`, writeLine);
|
|
349
368
|
if (!packageResult.ok) {
|
|
350
369
|
packagesOk = false;
|
|
351
370
|
continue;
|
|
@@ -403,6 +422,20 @@ export async function runMearlLifecycle(options, dependencies = {}) {
|
|
|
403
422
|
}
|
|
404
423
|
}
|
|
405
424
|
}
|
|
425
|
+
if (packagesOk && options.operation !== 'uninstall' && (stagedPreset || dependencies.prepareSkills)) {
|
|
426
|
+
try {
|
|
427
|
+
if (stagedPreset) {
|
|
428
|
+
const status = await stagedPreset.activate();
|
|
429
|
+
dependencies.onPresetStatus?.(status);
|
|
430
|
+
}
|
|
431
|
+
else
|
|
432
|
+
await dependencies.prepareSkills();
|
|
433
|
+
}
|
|
434
|
+
catch (error) {
|
|
435
|
+
writeLine(`Skill preparation: ${error instanceof Error ? error.message : String(error)}`);
|
|
436
|
+
packagesOk = false;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
406
439
|
const selectedUsesSkill = lifecycleSelected.some(profile => MEARL_PROFILES[profile].usesSkill);
|
|
407
440
|
const remainingSkillProfiles = ['local', 'cloud'].filter(profile => detected.has(profile) && !lifecycleSelected.includes(profile));
|
|
408
441
|
let runStandaloneSkill = true;
|
|
@@ -415,7 +448,7 @@ export async function runMearlLifecycle(options, dependencies = {}) {
|
|
|
415
448
|
(options.operation !== 'uninstall' && options.targetLine === undefined))) {
|
|
416
449
|
try {
|
|
417
450
|
if (options.operation === 'uninstall') {
|
|
418
|
-
const result = await (dependencies.
|
|
451
|
+
const result = await (dependencies.uninstallManagedPlugins ?? uninstallManagedPlugins)({
|
|
419
452
|
env,
|
|
420
453
|
includeMearlSkill: true,
|
|
421
454
|
runCommand: runner,
|
|
@@ -429,7 +462,7 @@ export async function runMearlLifecycle(options, dependencies = {}) {
|
|
|
429
462
|
}
|
|
430
463
|
}
|
|
431
464
|
else {
|
|
432
|
-
const result = await (dependencies.
|
|
465
|
+
const result = await (dependencies.installManagedPlugins ?? installManagedPlugins)({
|
|
433
466
|
env,
|
|
434
467
|
includeMearlSkill: true,
|
|
435
468
|
mearlSkillOperation: options.operation,
|
|
@@ -445,7 +478,7 @@ export async function runMearlLifecycle(options, dependencies = {}) {
|
|
|
445
478
|
}
|
|
446
479
|
}
|
|
447
480
|
catch (error) {
|
|
448
|
-
writeLine(`
|
|
481
|
+
writeLine(`Managed plugin batch: ${error instanceof Error ? error.message : String(error)}; failed.`);
|
|
449
482
|
runStandaloneSkill = false;
|
|
450
483
|
skillOk = false;
|
|
451
484
|
}
|
|
@@ -455,7 +488,7 @@ export async function runMearlLifecycle(options, dependencies = {}) {
|
|
|
455
488
|
if (options.operation === 'uninstall') {
|
|
456
489
|
if (remainingSkillProfiles.length > 0) {
|
|
457
490
|
writeLine(`Skill: kept for ${remainingSkillProfiles.join(', ')}.`);
|
|
458
|
-
writeLine(`
|
|
491
|
+
writeLine(`Managed plugins: kept for ${remainingSkillProfiles.join(', ')}.`);
|
|
459
492
|
}
|
|
460
493
|
else if (runStandaloneSkill) {
|
|
461
494
|
skillOk = await runSkill('uninstall', {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { findPluginRegistration, readOfficialPluginCatalog } from '@mearl/client/plugin';
|
|
2
|
+
import { installPlugins, uninstallPlugin } from './plugin.js';
|
|
3
|
+
import { runGlobalMearlSkillOperation } from './skills.js';
|
|
4
|
+
import { type CommandRunner } from '@mearl/daemon-core';
|
|
5
|
+
export interface ManagedPluginOptions {
|
|
6
|
+
env?: NodeJS.ProcessEnv;
|
|
7
|
+
includeMearlSkill?: boolean;
|
|
8
|
+
mearlSkillOperation?: 'install' | 'update';
|
|
9
|
+
runCommand?: CommandRunner;
|
|
10
|
+
writeLine?: (line: string) => void;
|
|
11
|
+
}
|
|
12
|
+
export interface ManagedPluginDependencies {
|
|
13
|
+
readCatalog?: typeof readOfficialPluginCatalog;
|
|
14
|
+
findPluginRegistration?: typeof findPluginRegistration;
|
|
15
|
+
installPlugins?: typeof installPlugins;
|
|
16
|
+
uninstallPlugin?: typeof uninstallPlugin;
|
|
17
|
+
runSkillOperation?: typeof runGlobalMearlSkillOperation;
|
|
18
|
+
}
|
|
19
|
+
/** Only the selected preset's managed registrations participate in lifecycle updates. */
|
|
20
|
+
export declare function installManagedPlugins(options?: ManagedPluginOptions, dependencies?: ManagedPluginDependencies): Promise<'installed' | 'skipped' | 'failed'>;
|
|
21
|
+
export declare function uninstallManagedPlugins(options?: ManagedPluginOptions, dependencies?: ManagedPluginDependencies): Promise<'uninstalled' | 'skipped' | 'failed'>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { findPluginRegistration, readOfficialPluginCatalog, OFFICIAL_PLUGIN_MANAGER } from '@mearl/client/plugin';
|
|
2
|
+
import { installPlugins, uninstallPlugin } from './plugin.js';
|
|
3
|
+
import { runGlobalMearlSkillOperation } from './skills.js';
|
|
4
|
+
import { runCommand } from '@mearl/daemon-core';
|
|
5
|
+
/** Only the selected preset's managed registrations participate in lifecycle updates. */
|
|
6
|
+
export async function installManagedPlugins(options = {}, dependencies = {}) {
|
|
7
|
+
const writeLine = options.writeLine ?? (line => console.error(line));
|
|
8
|
+
try {
|
|
9
|
+
const catalog = (dependencies.readCatalog ?? readOfficialPluginCatalog)();
|
|
10
|
+
if (!catalog || Object.keys(catalog.plugins).length === 0)
|
|
11
|
+
return 'skipped';
|
|
12
|
+
const registrationFor = dependencies.findPluginRegistration ?? findPluginRegistration;
|
|
13
|
+
const candidates = Object.entries(catalog.plugins).filter(([name]) => {
|
|
14
|
+
const registration = registrationFor(name);
|
|
15
|
+
if (registration && registration.managedBy !== OFFICIAL_PLUGIN_MANAGER) {
|
|
16
|
+
writeLine(`${name} plugin: existing user registration kept.`);
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
return true;
|
|
20
|
+
});
|
|
21
|
+
if (candidates.length === 0)
|
|
22
|
+
return 'skipped';
|
|
23
|
+
if (options.includeMearlSkill && !await (dependencies.runSkillOperation ?? runGlobalMearlSkillOperation)(options.mearlSkillOperation ?? 'install', {
|
|
24
|
+
env: options.env, runCommand: options.runCommand, writeLine, yes: true,
|
|
25
|
+
}))
|
|
26
|
+
return 'failed';
|
|
27
|
+
for (const [name, definition] of candidates) {
|
|
28
|
+
const code = await (dependencies.installPlugins ?? installPlugins)([...definition.installArgs], options.runCommand ?? runCommand, { registrationManagedBy: OFFICIAL_PLUGIN_MANAGER, env: options.env });
|
|
29
|
+
if (code !== 0) {
|
|
30
|
+
writeLine(`${name} plugin: install failed (exit ${code}).`);
|
|
31
|
+
return 'failed';
|
|
32
|
+
}
|
|
33
|
+
if (registrationFor(name)?.managedBy !== OFFICIAL_PLUGIN_MANAGER) {
|
|
34
|
+
writeLine(`${name} plugin: installation did not create its managed registration.`);
|
|
35
|
+
return 'failed';
|
|
36
|
+
}
|
|
37
|
+
writeLine(`${name} plugin: installed and registered.`);
|
|
38
|
+
}
|
|
39
|
+
return 'installed';
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
writeLine(`Managed plugin batch: ${error instanceof Error ? error.message : String(error)}; failed.`);
|
|
43
|
+
return 'failed';
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export async function uninstallManagedPlugins(options = {}, dependencies = {}) {
|
|
47
|
+
const writeLine = options.writeLine ?? (line => console.error(line));
|
|
48
|
+
try {
|
|
49
|
+
const catalog = (dependencies.readCatalog ?? readOfficialPluginCatalog)();
|
|
50
|
+
if (!catalog)
|
|
51
|
+
return 'skipped';
|
|
52
|
+
const registrationFor = dependencies.findPluginRegistration ?? findPluginRegistration;
|
|
53
|
+
for (const name of Object.keys(catalog.plugins)) {
|
|
54
|
+
const registration = registrationFor(name);
|
|
55
|
+
if (!registration)
|
|
56
|
+
continue;
|
|
57
|
+
if (registration.managedBy !== OFFICIAL_PLUGIN_MANAGER) {
|
|
58
|
+
writeLine(`${name} plugin: existing user registration kept.`);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
await (dependencies.uninstallPlugin ?? uninstallPlugin)(name, options.runCommand ?? runCommand, { preserveRegistrationsOutsideManager: OFFICIAL_PLUGIN_MANAGER, env: options.env });
|
|
62
|
+
if (registrationFor(name)) {
|
|
63
|
+
writeLine(`${name} plugin: uninstall did not clear its registration.`);
|
|
64
|
+
return 'failed';
|
|
65
|
+
}
|
|
66
|
+
writeLine(`${name} plugin: uninstalled.`);
|
|
67
|
+
}
|
|
68
|
+
if (options.includeMearlSkill && !await (dependencies.runSkillOperation ?? runGlobalMearlSkillOperation)('uninstall', { env: options.env, runCommand: options.runCommand, writeLine, yes: true }))
|
|
69
|
+
return 'failed';
|
|
70
|
+
return 'uninstalled';
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
writeLine(`Managed plugin batch: ${error instanceof Error ? error.message : String(error)}; failed.`);
|
|
74
|
+
return 'failed';
|
|
75
|
+
}
|
|
76
|
+
}
|
package/dist/npmRegistry.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export declare const OFFICIAL_NPM_REGISTRY = "https://registry.npmjs.org/";
|
|
2
|
-
|
|
2
|
+
/** Core packages use their public registry; other scopes retain the caller's configuration. */
|
|
3
3
|
export declare function packageRegistryEnvironment(packageName: string, env: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
package/dist/npmRegistry.js
CHANGED
|
@@ -1,20 +1,8 @@
|
|
|
1
1
|
export const OFFICIAL_NPM_REGISTRY = 'https://registry.npmjs.org/';
|
|
2
|
-
|
|
2
|
+
/** Core packages use their public registry; other scopes retain the caller's configuration. */
|
|
3
3
|
export function packageRegistryEnvironment(packageName, env) {
|
|
4
|
-
|
|
5
|
-
const registry = scope === '@mearl'
|
|
6
|
-
? OFFICIAL_NPM_REGISTRY
|
|
7
|
-
: scope === '@ali'
|
|
8
|
-
? ALIBABA_NPM_REGISTRY
|
|
9
|
-
: undefined;
|
|
10
|
-
if (!registry)
|
|
4
|
+
if (packageName.split('/')[0] !== '@mearl')
|
|
11
5
|
return env;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
...env,
|
|
15
|
-
npm_config_registry: registry,
|
|
16
|
-
NPM_CONFIG_REGISTRY: registry,
|
|
17
|
-
BUN_CONFIG_REGISTRY: registry,
|
|
18
|
-
[`npm_config_${scope}:registry`]: registry,
|
|
19
|
-
};
|
|
6
|
+
return { ...env, npm_config_registry: OFFICIAL_NPM_REGISTRY, NPM_CONFIG_REGISTRY: OFFICIAL_NPM_REGISTRY,
|
|
7
|
+
BUN_CONFIG_REGISTRY: OFFICIAL_NPM_REGISTRY, 'npm_config_@mearl:registry': OFFICIAL_NPM_REGISTRY };
|
|
20
8
|
}
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type PluginCatalogSelection } from '@mearl/client/plugin';
|
|
2
|
+
import { type InstalledSkill } from './skills.js';
|
|
1
3
|
import { type CommandRunner } from '@mearl/daemon-core';
|
|
2
4
|
export interface PluginSetupResult {
|
|
3
5
|
entry: string;
|
|
@@ -11,9 +13,17 @@ export interface PluginUninstallResult {
|
|
|
11
13
|
skillName?: string;
|
|
12
14
|
unregisteredNames: string[];
|
|
13
15
|
}
|
|
14
|
-
export declare function uninstallPlugin(name: string, runner?: CommandRunner
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
export declare function uninstallPlugin(name: string, runner?: CommandRunner, options?: {
|
|
17
|
+
preserveRegistrationsOutsideManager?: string;
|
|
18
|
+
env?: NodeJS.ProcessEnv;
|
|
19
|
+
}): Promise<PluginUninstallResult>;
|
|
20
|
+
/** Skills 的 Installed 区块列出成功路径;计数校验避免输出变化导致漏注册。 */
|
|
21
|
+
export declare function parseInstalledPluginPaths(output: string, listed?: InstalledSkill[]): string[];
|
|
17
22
|
export declare function installPlugins(args: string[], runner?: CommandRunner, options?: {
|
|
18
23
|
registrationManagedBy?: string;
|
|
24
|
+
env?: NodeJS.ProcessEnv;
|
|
25
|
+
selection?: PluginCatalogSelection;
|
|
26
|
+
expectedSkill?: string;
|
|
27
|
+
expectedPluginName?: string;
|
|
28
|
+
confirm?: () => void | Promise<void>;
|
|
19
29
|
}): Promise<number>;
|