@mearl/setup 2.20.3 → 2.20.4

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
@@ -106,6 +106,8 @@ npx @mearl/setup provider uninstall brow
106
106
  - `--local`、`--cloud` 与 `--mcp` 可以组合,显式传入时只处理选中的环境;
107
107
  `--qoder-cloud` 选择相同的 cloud 环境并记录 Qoder 配对模式,不能与 `--cloud` 同时使用。
108
108
  - 已有环境沿用其原包管理器和全局安装前缀;首次安装沿用启动 setup 的包管理器。
109
+ - `uninstall` 也识别 `npm link` 或 `dev:link` 注册到 npm 全局目录的开发软链,
110
+ 通过原 npm 前缀移除包与命令链接,保留仓库源码。安装和更新的自动检测仅处理常规全局安装。
109
111
  - cloud 环境统一管理 `@mearl/cloud-server` 与 `@mearl/client`:WebSocket 模式首次安装后
110
112
  启动 Server,更新后仅在 Server 原本运行时重启;Qoder 模式由相同的 `start` 命令生成
111
113
  新配对但不起服务;卸载前均调用 `stop`。
@@ -1,7 +1,7 @@
1
1
  import { listPluginNames } from '@mearl/client/plugin';
2
2
  import { listInstalledProviders } from '@mearl/provider/host';
3
3
  import { runGlobalMearlSkillOperation } from './aliSkills.js';
4
- import { detectGlobalPackage, type PackageManagerInstallation } from './packageManager.js';
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 './process.js';
@@ -26,7 +26,7 @@ export interface MearlLifecycleDependencies {
26
26
  cleanupNativeHost?: typeof uninstallNativeHostArtifacts;
27
27
  confirm?: (message: string) => Promise<boolean>;
28
28
  detectPackage?: typeof detectGlobalPackage;
29
- detectProfiles?: (env: NodeJS.ProcessEnv) => DetectedMearlProfiles;
29
+ detectProfiles?: (env: NodeJS.ProcessEnv, options?: Pick<PackageDetectionOptions, 'includeLinked'>) => DetectedMearlProfiles;
30
30
  existsSync?: (filePath: string) => boolean;
31
31
  installInternalPlugins?: typeof installAlibabaInternalPlugins;
32
32
  listPlugins?: typeof listPluginNames;
package/dist/lifecycle.js CHANGED
@@ -178,7 +178,8 @@ export async function runMearlLifecycle(options, dependencies = {}) {
178
178
  const runner = dependencies.runCommand ?? runCommand;
179
179
  const cleanupNativeHost = dependencies.cleanupNativeHost ?? uninstallNativeHostArtifacts;
180
180
  const detectPackage = dependencies.detectPackage ?? detectGlobalPackage;
181
- const detectProfiles = dependencies.detectProfiles ?? (childEnv => detectMearlProfiles({ env: childEnv }));
181
+ const detectProfiles = dependencies.detectProfiles ??
182
+ ((childEnv, detectionOptions) => detectMearlProfiles({ env: childEnv, ...detectionOptions }));
182
183
  const resolveInvokingManager = dependencies.resolveInvokingManager ??
183
184
  (childEnv => resolveInvokingPackageManager({ env: childEnv }));
184
185
  const runSkill = dependencies.runSkillOperation ?? runGlobalMearlSkillOperation;
@@ -186,7 +187,13 @@ export async function runMearlLifecycle(options, dependencies = {}) {
186
187
  const detectionEnv = options.operation === 'update' && env.MEARL_AUTO_UPDATE_SEARCH_PATH !== undefined
187
188
  ? { ...env, PATH: env.MEARL_AUTO_UPDATE_SEARCH_PATH }
188
189
  : env;
189
- const detected = detectProfiles(detectionEnv);
190
+ const detected = options.operation === 'uninstall'
191
+ ? detectProfiles(detectionEnv, { includeLinked: true })
192
+ : detectProfiles(detectionEnv);
193
+ const packageDetectionOptions = {
194
+ env,
195
+ ...(options.operation === 'uninstall' ? { includeLinked: true } : {}),
196
+ };
190
197
  const requestedProfiles = options.profiles ??
191
198
  (options.profile ? [options.profile] : undefined) ??
192
199
  (options.operation === 'update' ? autoUpdateProfiles(env) : undefined);
@@ -275,7 +282,7 @@ export async function runMearlLifecycle(options, dependencies = {}) {
275
282
  }
276
283
  let packagesOk = true;
277
284
  if (lifecycleSelected.includes('cloud')) {
278
- const legacyCloudClient = detectPackage(LEGACY_CLOUD_CLIENT, ['mearl-cloud'], { env });
285
+ const legacyCloudClient = detectPackage(LEGACY_CLOUD_CLIENT, ['mearl-cloud'], packageDetectionOptions);
279
286
  if (legacyCloudClient?.packageName === LEGACY_CLOUD_CLIENT) {
280
287
  const command = buildGlobalPackageCommand(legacyCloudClient, 'uninstall', [
281
288
  LEGACY_CLOUD_CLIENT,
@@ -293,7 +300,7 @@ export async function runMearlLifecycle(options, dependencies = {}) {
293
300
  const selectedUsesClient = autoUpdateClient !== null ||
294
301
  lifecycleSelected.some(profile => CLIENT_PROFILES.includes(profile));
295
302
  const detectedClientCandidate = selectedUsesClient && !autoUpdateClient
296
- ? detectPackage(UNIFIED_CLIENT, ['mearl'], { env })
303
+ ? detectPackage(UNIFIED_CLIENT, ['mearl'], packageDetectionOptions)
297
304
  : null;
298
305
  const detectedClient = detectedClientCandidate?.packageName === UNIFIED_CLIENT ? detectedClientCandidate : null;
299
306
  const remainingClientProfiles = selectedUsesClient && options.operation === 'uninstall'
@@ -17,6 +17,8 @@ export interface DetectedGlobalPackage extends PackageManagerInstallation {
17
17
  executable: string;
18
18
  }
19
19
  export interface PackageDetectionOptions {
20
+ /** Include npm global links when selecting packages for explicit removal. */
21
+ includeLinked?: boolean;
20
22
  env?: NodeJS.ProcessEnv;
21
23
  existsSync?: (filePath: string) => boolean;
22
24
  platform?: NodeJS.Platform;
@@ -224,7 +224,20 @@ export function detectGlobalPackage(packageName, binNames, options = {}) {
224
224
  const cli = detectCliPackage(packageName, [binName], options);
225
225
  if (!cli)
226
226
  continue;
227
- const installation = resolvePackageManagerInstallation(cli.packageRoot, packageName, options);
227
+ let installation = resolvePackageManagerInstallation(cli.packageRoot, packageName, options);
228
+ if (!installation && options.includeLinked) {
229
+ const linkedRoot = path.resolve(path.dirname(cli.executable), '../lib/node_modules', packageName);
230
+ try {
231
+ // A global package link must resolve to the package owning this CLI;
232
+ // an arbitrary executable symlink does not establish npm ownership.
233
+ if ((options.realpathSync ?? fs.realpathSync)(linkedRoot) === cli.packageRoot) {
234
+ installation = resolvePackageManagerInstallation(linkedRoot, packageName, options);
235
+ }
236
+ }
237
+ catch {
238
+ // The global package registration may be absent or a stale symlink.
239
+ }
240
+ }
228
241
  if (!installation)
229
242
  continue;
230
243
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mearl/setup",
3
- "version": "2.20.3",
3
+ "version": "2.20.4",
4
4
  "description": "One-shot environment setup and configuration for Mearl",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -69,8 +69,8 @@
69
69
  "commander": "^15.0.0",
70
70
  "extract-zip": "^2.0.1",
71
71
  "ws": "^8.18.3",
72
- "@mearl/provider": "2.20.3",
73
- "@mearl/client": "2.20.3"
72
+ "@mearl/client": "2.20.4",
73
+ "@mearl/provider": "2.20.4"
74
74
  },
75
75
  "devDependencies": {
76
76
  "@types/node": "^24.9.1",