@mearl/setup 2.16.2 → 2.16.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,8 @@ Mearl 环境的一次性安装、更新、卸载与配置工具。无需先全
4
4
 
5
5
  ```bash
6
6
  npx @mearl/setup [install] [--local] [--cloud|--qoder-cloud] [--mcp]
7
- npx @mearl/setup <update|uninstall> [--local] [--cloud|--qoder-cloud] [--mcp]
7
+ npx @mearl/setup update [--local] [--cloud|--qoder-cloud] [--mcp]
8
+ npx @mearl/setup uninstall [--local] [--cloud|--qoder-cloud] [--mcp] [--full]
8
9
  npx @mearl/setup extension [--full] [--force]
9
10
  npx @mearl/setup plugin <name> <path>
10
11
  npx @mearl/setup plugin install <ali-skills add 参数...>
@@ -110,9 +111,13 @@ npx @mearl/setup provider uninstall brow
110
111
  - local/cloud 共用一份 `@mearl/client`;组合安装只处理一次,卸载单个环境时若另一个环境仍在使用则保留。
111
112
  - 从 2.5.x 更新 cloud 环境时会先卸载旧 `@mearl/cloud-client`,避免它遗留的 `mearl` bin 与统一 client 冲突。
112
113
  - local/cloud 共用的全局 mearl skill 通过 `ali-skills` 的 JSON 清单定位,只处理一次。
113
- - 安装始终通过 `ali-skills add` 写入最新的全局 mearl skill,并关联当前检测到的 Agent;
114
+ - 安装始终通过 `ali-skills add --install-mode symlink` 写入最新的全局 mearl skill,并关联当前检测到的 Agent;
114
115
  可用 `--skip-skill` 跳过。
115
116
  - 卸载一个环境但另一个仍依赖全局 mearl skill 时会保留 skill。
117
+ - `uninstall --full` 在环境卸载之外,还会逐项卸载所有已注册 CLI 插件与浏览器 Provider。
118
+ Ali Skills 安装的插件会同时移除 Skill;手工注册的外部插件只清除注册、保留源码;Provider
119
+ 只有在包管理器成功卸载 npm 包后才清除注册。单项失败不阻止其他项继续清理,命令最终返回非零。
120
+ 该选项不删除 Chrome 扩展;`extension --full` 仍表示安装扩展及完整本地环境。
116
121
  - `--mcp` 的客户端配置和清理由 `@mearl/mcp-server` 自己的命令完成。
117
122
  - 默认的 `install` / `update` 不处理浏览器扩展。`extension` 是独立命令:从
118
123
  `https://mearl.alibaba-inc.com/` 识别并下载最新的 `mearl-chrome-v*.zip`,原子解压到
@@ -215,6 +220,9 @@ npx @mearl/setup uninstall --local
215
220
  # 自动检测并无交互卸载
216
221
  npx @mearl/setup uninstall --yes
217
222
 
223
+ # 卸载环境,并清理全部 CLI 插件与 Provider
224
+ npx @mearl/setup uninstall --full
225
+
218
226
  # 安装可选浏览器 Provider
219
227
  npx @mearl/setup provider install @ali/mearl-provider-brow
220
228
  npx @mearl/setup provider install @ali/mearl-provider-agentbay
package/dist/aliSkills.js CHANGED
@@ -164,7 +164,16 @@ export async function runGlobalMearlSkillOperation(operation, options = {}) {
164
164
  }
165
165
  };
166
166
  if (operation === 'install') {
167
- const installed = await run(['add', 'trip/mearl', '--skill', 'mearl', '--global', ...(options.yes ? ['--yes'] : [])], false);
167
+ const installed = await run([
168
+ 'add',
169
+ 'trip/mearl',
170
+ '--skill',
171
+ 'mearl',
172
+ '--global',
173
+ '--install-mode',
174
+ 'symlink',
175
+ ...(options.yes ? ['--yes'] : []),
176
+ ], false);
168
177
  if (!installed)
169
178
  return false;
170
179
  if (installed.code !== 0) {
package/dist/cli.js CHANGED
@@ -70,8 +70,10 @@ export function parseSetupArgs(argv) {
70
70
  .option('--target-line <major.minor.x>')
71
71
  .option('--skip-skill')
72
72
  .option('-y, --yes')
73
- .option('--non-interactive')
74
- .action(() => {
73
+ .option('--non-interactive');
74
+ if (operation === 'uninstall')
75
+ command.option('--full');
76
+ command.action(() => {
75
77
  const options = command.opts();
76
78
  if (options.cloud && options.qoderCloud) {
77
79
  throw new Error('--cloud and --qoder-cloud cannot be used together');
@@ -96,6 +98,7 @@ export function parseSetupArgs(argv) {
96
98
  ? { cloudMode: options.qoderCloud ? 'qoder' : 'websocket' }
97
99
  : {}),
98
100
  ...(profiles.length > 0 ? { profiles } : {}),
101
+ ...(options.full ? { full: true } : {}),
99
102
  skipSkill: options.skipSkill === true,
100
103
  targetLine: options.targetLine,
101
104
  yes: options.yes === true || options.nonInteractive === true,
@@ -150,63 +153,59 @@ export function parseSetupArgs(argv) {
150
153
  throw new Error('No setup operation was selected');
151
154
  return parsed;
152
155
  }
153
- function printHelp(toError = false) {
156
+ function printHelp() {
154
157
  const output = `Mearl Setup v${SETUP_VERSION}
155
158
 
156
159
  Usage:
157
- npx @mearl/setup [install] [--local] [--cloud|--qoder-cloud] [--mcp] [--yes]
158
- npx @mearl/setup <update|uninstall> [--local] [--cloud|--qoder-cloud] [--mcp] [--yes]
159
- npx @mearl/setup extension [--full] [--force] [--yes]
160
- npx @mearl/setup plugin <name> <path>
161
- npx @mearl/setup plugin install <ali-skills add arguments...>
162
- npx @mearl/setup plugin uninstall <name>
163
- npx @mearl/setup provider <install|update|uninstall> <package|id>
160
+ npx @mearl/setup [command] [options]
164
161
 
165
- Behavior:
166
- install Default command; defaults to --local when no environment is specified
167
- update Auto-detects installed environments from the current PATH
168
- uninstall Auto-detects installed environments and asks for confirmation
169
- extension Install or update the browser extension; --full also installs the local environment
170
- plugin Register, install, or uninstall a CLI plugin
171
- provider Install npm Provider packages and manage their Mearl registration
162
+ Environment commands:
163
+ install [options] Install an environment (default command; target: local)
164
+ update [options] Update detected or selected environments
165
+ uninstall [options] Uninstall detected or selected environments
172
166
 
173
- Options:
174
- --local Manage @mearl/native-host and @mearl/client
175
- --cloud Manage cloud packages in WebSocket server mode
176
- --qoder-cloud
177
- Manage the same cloud packages in Qoder pairing mode
178
- --mcp Manage @mearl/mcp-server and its configuration
179
- --target-line <major.minor.x>
180
- Install the latest packages from one release line, such as 2.3.x
181
- --skip-skill Keep the independently managed Mearl Skill unchanged
182
- --full Also install @mearl/client, @mearl/native-host, and the Mearl Skill
183
- --force Replace an existing store, managed, or other local Mearl extension
184
- --yes, -y Run without prompts and accept detected defaults
185
- --non-interactive
186
- Alias for --yes, intended for Agents and CI
187
- --version, -v
188
- Show version
189
- --help, -h Show this help
167
+ Integration commands:
168
+ plugin install <arguments...> Install Skills and register their CLI plugins
169
+ plugin uninstall <name> Uninstall one CLI plugin
170
+ plugin <name> <path> Register an existing plugin entry
171
+ provider install <package> Install and register a Provider package
172
+ provider update <id|package> Update a registered Provider package
173
+ provider uninstall <id|package> Uninstall a Provider package and registration
174
+
175
+ Browser extension:
176
+ extension [--full] [--force] Install or update the browser extension
177
+
178
+ Environment options:
179
+ --local Manage @mearl/native-host and @mearl/client
180
+ --cloud Manage cloud packages in WebSocket server mode
181
+ --qoder-cloud Manage cloud packages in Qoder pairing mode
182
+ --mcp Manage @mearl/mcp-server and its configuration
183
+ --target-line <major.minor.x> Use the latest packages in one release line
184
+ --skip-skill Keep the independently managed Mearl Skill unchanged
185
+
186
+ Uninstall options:
187
+ --full Remove all CLI plugins and Provider packages/registrations
188
+
189
+ Extension options:
190
+ --full Install the extension and complete local environment
191
+ --force Replace an extension managed by another source
192
+
193
+ General options:
194
+ --yes, -y Accept prompts and detected defaults
195
+ --non-interactive Alias for --yes, intended for Agents and CI
196
+ --version, -v Show version
197
+ --help, -h Show this help
190
198
 
191
199
  Examples:
192
200
  npx @mearl/setup
193
- npx @mearl/setup --yes
194
- npx @mearl/setup install
195
201
  npx @mearl/setup --cloud
196
202
  npx @mearl/setup --local --cloud
197
203
  npx @mearl/setup update
198
- npx @mearl/setup extension
199
- npx @mearl/setup extension --full
204
+ npx @mearl/setup uninstall --full
200
205
  npx @mearl/setup plugin uninstall yuque
201
206
  npx @mearl/setup provider install @ali/mearl-provider-brow
202
- npx @mearl/setup provider install @ali/mearl-provider-agentbay
203
- npx @mearl/setup --qoder-cloud --yes
204
- npx @mearl/setup update --local --target-line 2.3.x --skip-skill
205
- npx @mearl/setup uninstall --local`;
206
- if (toError)
207
- console.error(output);
208
- else
209
- console.log(output);
207
+ npx @mearl/setup extension --full`;
208
+ console.log(output);
210
209
  }
211
210
  export async function main(argv = process.argv.slice(2), interactiveTerminal = process.stdin.isTTY === true && process.stdout.isTTY === true, dependencies = {}) {
212
211
  let parsed;
@@ -215,7 +214,7 @@ export async function main(argv = process.argv.slice(2), interactiveTerminal = p
215
214
  }
216
215
  catch (error) {
217
216
  console.error(error instanceof Error ? error.message : String(error));
218
- printHelp(true);
217
+ console.error('Run "npx @mearl/setup --help" for usage.');
219
218
  return 2;
220
219
  }
221
220
  if (parsed.help) {
@@ -346,6 +345,7 @@ export async function main(argv = process.argv.slice(2), interactiveTerminal = p
346
345
  operation: parsed.operation,
347
346
  profiles: parsed.profiles,
348
347
  cloudMode: parsed.cloudMode,
348
+ full: parsed.full,
349
349
  skipSkill: parsed.skipSkill,
350
350
  targetLine: parsed.targetLine,
351
351
  yes: parsed.yes,
@@ -1,13 +1,19 @@
1
+ import { listPluginNames } from '@mearl/client/plugin';
2
+ import { listInstalledProviders } from '@mearl/provider/host';
1
3
  import { runGlobalMearlSkillOperation } from './aliSkills.js';
2
4
  import { detectGlobalPackage, type PackageManagerInstallation } from './packageManager.js';
3
5
  import { type DetectedMearlProfiles, type MearlProfile } from './profiles.js';
4
6
  import { uninstallNativeHostArtifacts } from './nativeHost.js';
5
7
  import { type CommandRunner } from './process.js';
6
8
  import { installAlibabaInternalPlugins, uninstallAlibabaInternalPlugins } from './internalPlugins.js';
9
+ import { uninstallPlugin } from './plugin.js';
10
+ import { uninstallProviderPackage } from './provider.js';
7
11
  export type MearlLifecycleOperation = 'install' | 'update' | 'uninstall';
8
12
  export interface MearlLifecycleOptions {
9
13
  operation: MearlLifecycleOperation;
10
14
  cloudMode?: 'websocket' | 'qoder';
15
+ /** Uninstall every registered CLI plugin and Provider in addition to selected environments. */
16
+ full?: boolean;
11
17
  /** @deprecated Use profiles when selecting one or more composable environments. */
12
18
  profile?: MearlProfile;
13
19
  profiles?: MearlProfile[];
@@ -23,10 +29,14 @@ export interface MearlLifecycleDependencies {
23
29
  detectProfiles?: (env: NodeJS.ProcessEnv) => DetectedMearlProfiles;
24
30
  existsSync?: (filePath: string) => boolean;
25
31
  installInternalPlugins?: typeof installAlibabaInternalPlugins;
32
+ listPlugins?: typeof listPluginNames;
33
+ listProviders?: typeof listInstalledProviders;
26
34
  resolveInvokingManager?: (env: NodeJS.ProcessEnv) => PackageManagerInstallation;
27
35
  runCommand?: CommandRunner;
28
36
  runSkillOperation?: typeof runGlobalMearlSkillOperation;
29
37
  uninstallInternalPlugins?: typeof uninstallAlibabaInternalPlugins;
38
+ uninstallPlugin?: typeof uninstallPlugin;
39
+ uninstallProvider?: typeof uninstallProviderPackage;
30
40
  writeLine?: (line: string) => void;
31
41
  }
32
42
  export declare function runMearlLifecycle(options: MearlLifecycleOptions, dependencies?: MearlLifecycleDependencies): Promise<boolean>;
package/dist/lifecycle.js CHANGED
@@ -2,6 +2,8 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { createInterface } from 'node:readline/promises';
4
4
  import { stdin as input, stdout as output } from 'node:process';
5
+ import { listPluginNames } from '@mearl/client/plugin';
6
+ import { listInstalledProviders } from '@mearl/provider/host';
5
7
  import { runGlobalMearlSkillOperation } from './aliSkills.js';
6
8
  import { buildGlobalPackageCommand, detectGlobalPackage, resolveInvokingPackageManager, } from './packageManager.js';
7
9
  import { MEARL_PROFILES, detectMearlProfiles, } from './profiles.js';
@@ -9,6 +11,8 @@ import { uninstallNativeHostArtifacts } from './nativeHost.js';
9
11
  import { executableNames, prependCommandPath, runCommand, } from './process.js';
10
12
  import { isMearlReleaseLine } from './version.js';
11
13
  import { installAlibabaInternalPlugins, uninstallAlibabaInternalPlugins, } from './internalPlugins.js';
14
+ import { uninstallPlugin } from './plugin.js';
15
+ import { uninstallProviderPackage } from './provider.js';
12
16
  const LEGACY_CLOUD_CLIENT = '@mearl/cloud-client';
13
17
  const UNIFIED_CLIENT = '@mearl/client';
14
18
  const PROFILE_ORDER = ['local', 'cloud', 'mcp'];
@@ -152,7 +156,37 @@ export async function runMearlLifecycle(options, dependencies = {}) {
152
156
  const detected = detectProfiles(env);
153
157
  const requestedProfiles = options.profiles ?? (options.profile ? [options.profile] : undefined);
154
158
  const selected = selectedProfiles(options.operation, requestedProfiles, detected);
155
- if (selected.length === 0) {
159
+ const lifecycleSelected = options.operation === 'uninstall'
160
+ ? selected.filter(profile => detected.has(profile))
161
+ : selected;
162
+ let fullPluginNames = [];
163
+ let fullProviders = [];
164
+ if (options.operation === 'uninstall' && options.full) {
165
+ try {
166
+ fullPluginNames = (dependencies.listPlugins ?? listPluginNames)();
167
+ }
168
+ catch (error) {
169
+ writeLine(`CLI plugins: unable to list registrations: ${error instanceof Error ? error.message : String(error)}`);
170
+ return false;
171
+ }
172
+ try {
173
+ fullProviders = (dependencies.listProviders ?? listInstalledProviders)();
174
+ }
175
+ catch (error) {
176
+ writeLine(`Providers: unable to list registrations: ${error instanceof Error ? error.message : String(error)}`);
177
+ return false;
178
+ }
179
+ }
180
+ const hasFullIntegrationTargets = fullPluginNames.length > 0 || fullProviders.length > 0;
181
+ if (options.operation === 'uninstall' &&
182
+ options.full &&
183
+ lifecycleSelected.length === 0 &&
184
+ !hasFullIntegrationTargets) {
185
+ writeLine('No installed Mearl environments, CLI plugins, or Providers were detected.');
186
+ return true;
187
+ }
188
+ if (selected.length === 0 &&
189
+ !(options.operation === 'uninstall' && options.full && hasFullIntegrationTargets)) {
156
190
  writeLine('No installed Mearl environment was detected on the current PATH.');
157
191
  if (options.operation === 'uninstall')
158
192
  return true;
@@ -167,22 +201,33 @@ export async function runMearlLifecycle(options, dependencies = {}) {
167
201
  }
168
202
  }
169
203
  if (options.operation === 'uninstall') {
170
- const installedSelected = selected.filter(profile => detected.has(profile));
171
- if (installedSelected.length === 0) {
204
+ if (lifecycleSelected.length === 0 && !options.full) {
172
205
  writeLine(`Nothing to uninstall for ${selected.join(', ')}.`);
173
206
  return true;
174
207
  }
208
+ if (options.full) {
209
+ writeLine(`CLI plugins: ${fullPluginNames.length > 0 ? fullPluginNames.join(', ') : 'none detected'}.`);
210
+ writeLine(`Providers: ${fullProviders.length > 0
211
+ ? fullProviders.map(provider => provider.providerId).join(', ')
212
+ : 'none detected'}.`);
213
+ }
175
214
  if (!options.yes &&
176
- !(await confirm(`Uninstall Mearl environments: ${installedSelected.join(', ')}?`))) {
215
+ !(await confirm(options.full
216
+ ? `Uninstall ${lifecycleSelected.length > 0
217
+ ? `Mearl environments (${lifecycleSelected.join(', ')}) and `
218
+ : ''}all CLI plugins and Providers?`
219
+ : `Uninstall Mearl environments: ${lifecycleSelected.join(', ')}?`))) {
177
220
  writeLine('Uninstall cancelled.');
178
221
  return false;
179
222
  }
180
223
  }
181
- writeLine(`${operationVerb(options.operation)} targets: ${selected
182
- .map(profile => MEARL_PROFILES[profile].label)
183
- .join(', ')}`);
224
+ if (lifecycleSelected.length > 0) {
225
+ writeLine(`${operationVerb(options.operation)} targets: ${lifecycleSelected
226
+ .map(profile => MEARL_PROFILES[profile].label)
227
+ .join(', ')}`);
228
+ }
184
229
  let packagesOk = true;
185
- if (selected.includes('cloud')) {
230
+ if (lifecycleSelected.includes('cloud')) {
186
231
  const legacyCloudClient = detectPackage(LEGACY_CLOUD_CLIENT, ['mearl-cloud'], { env });
187
232
  if (legacyCloudClient?.packageName === LEGACY_CLOUD_CLIENT) {
188
233
  const command = buildGlobalPackageCommand(legacyCloudClient, 'uninstall', [
@@ -198,13 +243,13 @@ export async function runMearlLifecycle(options, dependencies = {}) {
198
243
  }
199
244
  }
200
245
  }
201
- const selectedUsesClient = selected.some(profile => CLIENT_PROFILES.includes(profile));
246
+ const selectedUsesClient = lifecycleSelected.some(profile => CLIENT_PROFILES.includes(profile));
202
247
  const detectedClientCandidate = selectedUsesClient
203
248
  ? detectPackage(UNIFIED_CLIENT, ['mearl'], { env })
204
249
  : null;
205
250
  const detectedClient = detectedClientCandidate?.packageName === UNIFIED_CLIENT ? detectedClientCandidate : null;
206
251
  const remainingClientProfiles = selectedUsesClient && options.operation === 'uninstall'
207
- ? CLIENT_PROFILES.filter(profile => detected.has(profile) && !selected.includes(profile))
252
+ ? CLIENT_PROFILES.filter(profile => detected.has(profile) && !lifecycleSelected.includes(profile))
208
253
  : [];
209
254
  if (selectedUsesClient && options.operation !== 'uninstall') {
210
255
  const clientInstallation = detectedClient ??
@@ -217,7 +262,7 @@ export async function runMearlLifecycle(options, dependencies = {}) {
217
262
  return false;
218
263
  }
219
264
  }
220
- for (const profile of selected) {
265
+ for (const profile of lifecycleSelected) {
221
266
  const config = MEARL_PROFILES[profile];
222
267
  const current = detected.get(profile);
223
268
  if (options.operation === 'uninstall' && !current)
@@ -277,8 +322,40 @@ export async function runMearlLifecycle(options, dependencies = {}) {
277
322
  packagesOk = false;
278
323
  }
279
324
  }
280
- const selectedUsesSkill = selected.some(profile => MEARL_PROFILES[profile].usesSkill);
281
- const remainingSkillProfiles = ['local', 'cloud'].filter(profile => detected.has(profile) && !selected.includes(profile));
325
+ let fullOk = true;
326
+ if (options.operation === 'uninstall' && options.full) {
327
+ const pendingPlugins = new Set(fullPluginNames);
328
+ const removePlugin = dependencies.uninstallPlugin ?? uninstallPlugin;
329
+ while (pendingPlugins.size > 0) {
330
+ const name = pendingPlugins.values().next().value;
331
+ pendingPlugins.delete(name);
332
+ try {
333
+ const result = await removePlugin(name, runner);
334
+ for (const removedName of result.unregisteredNames)
335
+ pendingPlugins.delete(removedName);
336
+ if (result.removed) {
337
+ writeLine(`CLI plugin ${name}: uninstalled.`);
338
+ }
339
+ }
340
+ catch (error) {
341
+ fullOk = false;
342
+ writeLine(`CLI plugin ${name}: ${error instanceof Error ? error.message : String(error)}`);
343
+ }
344
+ }
345
+ const removeProvider = dependencies.uninstallProvider ?? uninstallProviderPackage;
346
+ for (const provider of fullProviders) {
347
+ try {
348
+ await removeProvider(provider.providerId);
349
+ writeLine(`Provider ${provider.providerId}: uninstalled.`);
350
+ }
351
+ catch (error) {
352
+ fullOk = false;
353
+ writeLine(`Provider ${provider.providerId}: ${error instanceof Error ? error.message : String(error)}`);
354
+ }
355
+ }
356
+ }
357
+ const selectedUsesSkill = lifecycleSelected.some(profile => MEARL_PROFILES[profile].usesSkill);
358
+ const remainingSkillProfiles = ['local', 'cloud'].filter(profile => detected.has(profile) && !lifecycleSelected.includes(profile));
282
359
  let runStandaloneSkill = true;
283
360
  let skillOk = true;
284
361
  if (packagesOk &&
@@ -354,7 +431,7 @@ export async function runMearlLifecycle(options, dependencies = {}) {
354
431
  skillOk = false;
355
432
  }
356
433
  }
357
- if (packagesOk && skillOk) {
434
+ if (packagesOk && skillOk && fullOk) {
358
435
  writeLine('Mearl setup complete.');
359
436
  return true;
360
437
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mearl/setup",
3
- "version": "2.16.2",
3
+ "version": "2.16.3",
4
4
  "description": "One-shot environment setup and configuration for Mearl",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -61,8 +61,8 @@
61
61
  "commander": "^15.0.0",
62
62
  "extract-zip": "^2.0.1",
63
63
  "ws": "^8.18.3",
64
- "@mearl/client": "2.16.2",
65
- "@mearl/provider": "2.16.2"
64
+ "@mearl/client": "2.16.3",
65
+ "@mearl/provider": "2.16.3"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@types/node": "^24.9.1",