@mearl/setup 2.22.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.
Files changed (42) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +59 -59
  3. package/dist/browserExtension.d.ts +2 -2
  4. package/dist/browserExtension.js +25 -19
  5. package/dist/cli.d.ts +8 -3
  6. package/dist/cli.js +74 -17
  7. package/dist/index.d.ts +3 -1
  8. package/dist/index.js +2 -1
  9. package/dist/lifecycle.d.ts +11 -4
  10. package/dist/lifecycle.js +48 -15
  11. package/dist/managedPlugins.d.ts +21 -0
  12. package/dist/managedPlugins.js +76 -0
  13. package/dist/npmRegistry.d.ts +1 -1
  14. package/dist/npmRegistry.js +4 -16
  15. package/dist/plugin.d.ts +13 -3
  16. package/dist/plugin.js +106 -44
  17. package/dist/preset.d.ts +94 -0
  18. package/dist/preset.js +275 -0
  19. package/dist/presetBrowserTransfer.d.ts +11 -0
  20. package/dist/presetBrowserTransfer.js +72 -0
  21. package/dist/presetInstallationLease.d.ts +6 -0
  22. package/dist/presetInstallationLease.js +66 -0
  23. package/dist/presetStore.d.ts +48 -0
  24. package/dist/presetStore.js +252 -0
  25. package/dist/presetUpgrade.d.ts +13 -0
  26. package/dist/presetUpgrade.js +42 -0
  27. package/dist/provider.d.ts +2 -0
  28. package/dist/provider.js +24 -2
  29. package/dist/runtimeCleanup.js +1 -8
  30. package/dist/setupVersion.d.ts +2 -0
  31. package/dist/setupVersion.js +4 -0
  32. package/dist/skillSources.d.ts +43 -0
  33. package/dist/skillSources.js +247 -0
  34. package/dist/skills.d.ts +45 -0
  35. package/dist/skills.js +213 -0
  36. package/dist/version.d.ts +2 -0
  37. package/dist/version.js +6 -0
  38. package/package.json +22 -10
  39. package/dist/aliSkills.d.ts +0 -32
  40. package/dist/aliSkills.js +0 -212
  41. package/dist/internalPlugins.d.ts +0 -26
  42. 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
- const require = createRequire(import.meta.url);
10
- export const SETUP_VERSION = require('../package.json').version;
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 @ali/mearl-provider-brow
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('Run "npx @mearl/setup --help" for usage.');
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; ali-skills cleanup completed for ${result.skillName}.`
254
- : `Plugin ${parsed.pluginUninstallName} uninstalled with ali-skills skill ${result.skillName}.`);
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('This Chrome version does not support installing extensions through CDP. Update Chrome to version 145 or later, then rerun: npx @mearl/setup extension');
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('Open chrome://inspect/#remote-debugging, enable remote debugging, approve the connection, then rerun: npx @mearl/setup extension');
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 localInstalled = false;
399
+ let localStatus = 1;
344
400
  try {
345
- localInstalled = await (dependencies.runLifecycle ?? runMearlLifecycle)({
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 && localInstalled ? 0 : 1;
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 ok = await (dependencies.runLifecycle ?? runMearlLifecycle)({
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
- return ok ? 0 : 1;
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';
@@ -1,16 +1,19 @@
1
1
  import { listPluginNames } from '@mearl/client/plugin';
2
2
  import { listInstalledProviders } from '@mearl/provider/host';
3
- import { runGlobalMearlSkillOperation } from './aliSkills.js';
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 { installAlibabaInternalPlugins, uninstallAlibabaInternalPlugins } from './internalPlugins.js';
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
- installInternalPlugins?: typeof installAlibabaInternalPlugins;
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
- uninstallInternalPlugins?: typeof uninstallAlibabaInternalPlugins;
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 './aliSkills.js';
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 { installAlibabaInternalPlugins, uninstallAlibabaInternalPlugins, } from './internalPlugins.js';
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.uninstallInternalPlugins ?? uninstallAlibabaInternalPlugins)({
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.installInternalPlugins ?? installAlibabaInternalPlugins)({
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(`Internal skill batch: ${error instanceof Error ? error.message : String(error)}; failed.`);
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(`Internal plugins: kept for ${remainingSkillProfiles.join(', ')}.`);
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
+ }
@@ -1,3 +1,3 @@
1
1
  export declare const OFFICIAL_NPM_REGISTRY = "https://registry.npmjs.org/";
2
- export declare const ALIBABA_NPM_REGISTRY = "https://registry.anpm.alibaba-inc.com/";
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;
@@ -1,20 +1,8 @@
1
1
  export const OFFICIAL_NPM_REGISTRY = 'https://registry.npmjs.org/';
2
- export const ALIBABA_NPM_REGISTRY = 'https://registry.anpm.alibaba-inc.com/';
2
+ /** Core packages use their public registry; other scopes retain the caller's configuration. */
3
3
  export function packageRegistryEnvironment(packageName, env) {
4
- const scope = packageName.split('/')[0];
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
- // npm-compatible managers and Bun receive the same registry, including scoped npm overrides.
13
- return {
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): Promise<PluginUninstallResult>;
15
- /** Ali Skills 的 Installed 区块列出成功路径;计数校验避免输出变化导致漏注册。 */
16
- export declare function parseInstalledPluginPaths(output: string): string[];
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>;