Sign In

@mearl/setup

Package Overview
Dependencies
Maintainers
2
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mearl/setup - npm Package Compare versions

Comparing version
2.5.1
to
2.6.0
+3
-1
dist/cli.d.ts

@@ -5,2 +5,3 @@ #!/usr/bin/env node

import type { MearlProfile } from './profiles.js';
export declare const SETUP_VERSION: string;
interface ParsedArgs {

@@ -11,5 +12,6 @@ agentBayKeyFile?: string;

operation?: MearlLifecycleOperation | 'agentbay';
profile?: MearlProfile;
profiles?: MearlProfile[];
skipSkill: boolean;
targetLine?: string;
version?: boolean;
yes: boolean;

@@ -16,0 +18,0 @@ }

#!/usr/bin/env node
import path from 'node:path';
import { createRequire } from 'node:module';
import { fileURLToPath } from 'node:url';

@@ -7,7 +8,20 @@ import { configureAgentBayApiKey, promptAgentBayApiKey, readAgentBayApiKeyFile, readAgentBayApiKeyStdin, } from './agentBay.js';

import { isMearlReleaseLine } from './version.js';
const require = createRequire(import.meta.url);
export const SETUP_VERSION = require('../package.json').version;
export function parseSetupArgs(argv) {
if (argv.length === 0 || argv.includes('--help') || argv.includes('-h')) {
if (argv.includes('--help') || argv.includes('-h')) {
return { agentBayReadStdin: false, help: true, skipSkill: false, yes: false };
}
const operation = argv[0];
if (argv.includes('--version') || argv.includes('-v')) {
return {
agentBayReadStdin: false,
help: false,
skipSkill: false,
version: true,
yes: false,
};
}
const firstArg = argv[0];
const operation = firstArg === undefined || firstArg.startsWith('-') ? 'install' : firstArg;
const optionStart = operation === firstArg ? 1 : 0;
if (operation === 'agentbay') {

@@ -47,7 +61,7 @@ if (argv.length === 1) {

}
let profile;
const profiles = [];
let skipSkill = false;
let targetLine;
let yes = false;
for (let index = 1; index < argv.length; index += 1) {
for (let index = optionStart; index < argv.length; index += 1) {
const arg = argv[index];

@@ -80,6 +94,4 @@ if (arg === '--yes' || arg === '-y' || arg === '--non-interactive') {

throw new Error(`Unknown option: ${arg}`);
if (profile && profile !== candidate) {
throw new Error('Choose only one of --local, --cloud, or --mcp');
}
profile = candidate;
if (!profiles.includes(candidate))
profiles.push(candidate);
}

@@ -93,3 +105,3 @@ if (operation === 'uninstall' && targetLine) {

operation,
profile,
...(profiles.length > 0 ? { profiles } : {}),
skipSkill,

@@ -100,11 +112,12 @@ targetLine,

}
function printHelp() {
console.error(`Mearl Setup
function printHelp(toError = false) {
const output = `Mearl Setup v${SETUP_VERSION}
Usage:
npx @mearl/setup <install|update|uninstall> [--local|--cloud|--mcp] [--yes]
npx @mearl/setup [install] [--local] [--cloud] [--mcp] [--yes]
npx @mearl/setup <update|uninstall> [--local] [--cloud] [--mcp] [--yes]
npx @mearl/setup agentbay [--stdin | --key-file <path>]
Behavior:
install Defaults to --local when no environment is specified
install Default command; defaults to --local when no environment is specified
update Auto-detects installed environments from the current PATH

@@ -116,3 +129,3 @@ uninstall Auto-detects installed environments and asks for confirmation

--local Manage @mearl/native-host and @mearl/client
--cloud Manage @mearl/cloud-server and @mearl/cloud-client
--cloud Manage @mearl/cloud-server and the unified @mearl/client
--mcp Manage @mearl/mcp-server and its configuration

@@ -127,12 +140,21 @@ --stdin Read the AgentBay API key from standard input

Alias for --yes, intended for Agents and CI
--version, -v
Show version
--help, -h Show this help
Examples:
npx @mearl/setup
npx @mearl/setup --yes
npx @mearl/setup install
npx @mearl/setup install --yes
npx @mearl/setup install --cloud
npx @mearl/setup install --local --cloud
npx @mearl/setup update
npx @mearl/setup agentbay
npx @mearl/setup update --local --target-line 2.3.x --skip-skill
npx @mearl/setup uninstall --local`);
npx @mearl/setup uninstall --local`;
if (toError)
console.error(output);
else
console.log(output);
}

@@ -146,3 +168,3 @@ export async function main(argv = process.argv.slice(2), interactiveTerminal = process.stdin.isTTY === true && process.stdout.isTTY === true, dependencies = {}) {

console.error(error instanceof Error ? error.message : String(error));
printHelp();
printHelp(true);
return 2;

@@ -154,2 +176,6 @@ }

}
if (parsed.version) {
console.log(SETUP_VERSION);
return 0;
}
if (parsed.operation === 'agentbay') {

@@ -187,3 +213,3 @@ try {

operation: parsed.operation,
profile: parsed.profile,
profiles: parsed.profiles,
skipSkill: parsed.skipSkill,

@@ -190,0 +216,0 @@ targetLine: parsed.targetLine,

@@ -9,3 +9,5 @@ import { runGlobalMearlSkillOperation } from './aliSkills.js';

operation: MearlLifecycleOperation;
/** @deprecated Use profiles when selecting one or more composable environments. */
profile?: MearlProfile;
profiles?: MearlProfile[];
yes?: boolean;

@@ -12,0 +14,0 @@ targetLine?: string;

@@ -11,2 +11,6 @@ import fs from 'node:fs';

import { isMearlReleaseLine } from './version.js';
const LEGACY_CLOUD_CLIENT = '@mearl/cloud-client';
const UNIFIED_CLIENT = '@mearl/client';
const PROFILE_ORDER = ['local', 'cloud', 'mcp'];
const CLIENT_PROFILES = ['local', 'cloud'];
async function confirmInTerminal(message) {

@@ -44,2 +48,14 @@ if (!input.isTTY || !output.isTTY)

}
async function runPackageOperation(installation, operation, packages, targetLine, runner, env, label, writeLine) {
const command = buildGlobalPackageCommand(installation, operation, packages, targetLine);
writeLine(`${label}: ${command.manager}`);
const result = await runLifecycleCommand(runner, command.command, command.args, env, label, writeLine);
if (!result)
return { command, ok: false };
if (result.code !== 0) {
writeLine(`${label}: failed (exit ${result.code}).`);
return { command, ok: false };
}
return { command, ok: true };
}
async function runHook(profile, operation, detected, runner, existsSync, env, writeLine, yes) {

@@ -106,7 +122,9 @@ let executable;

function selectedProfiles(operation, requested, detected) {
if (requested)
return [requested];
if (requested?.length) {
const requestedSet = new Set(requested);
return PROFILE_ORDER.filter(profile => requestedSet.has(profile));
}
if (operation === 'install')
return ['local'];
return [...detected.keys()];
return PROFILE_ORDER.filter(profile => detected.has(profile));
}

@@ -132,3 +150,4 @@ function operationVerb(operation) {

const detected = detectProfiles(env);
const selected = selectedProfiles(options.operation, options.profile, detected);
const requestedProfiles = options.profiles ?? (options.profile ? [options.profile] : undefined);
const selected = selectedProfiles(options.operation, requestedProfiles, detected);
if (selected.length === 0) {

@@ -164,2 +183,34 @@ writeLine('No installed Mearl environment was detected on the current PATH.');

let packagesOk = true;
if (selected.includes('cloud')) {
const legacyCloudClient = detectPackage(LEGACY_CLOUD_CLIENT, ['mearl-cloud'], { env });
if (legacyCloudClient?.packageName === LEGACY_CLOUD_CLIENT) {
const command = buildGlobalPackageCommand(legacyCloudClient, 'uninstall', [
LEGACY_CLOUD_CLIENT,
]);
writeLine(`Migration (cloud): removing ${LEGACY_CLOUD_CLIENT}.`);
const result = await runLifecycleCommand(runner, command.command, command.args, env, 'Migration (cloud)', writeLine);
if (!result || result.code !== 0) {
if (result)
writeLine(`Migration (cloud): failed (exit ${result.code}).`);
writeLine('Mearl setup incomplete. Review the messages above.');
return false;
}
}
}
const selectedUsesClient = selected.some(profile => CLIENT_PROFILES.includes(profile));
const detectedClientCandidate = selectedUsesClient
? detectPackage(UNIFIED_CLIENT, ['mearl'], { env })
: null;
const detectedClient = detectedClientCandidate?.packageName === UNIFIED_CLIENT ? detectedClientCandidate : null;
if (selectedUsesClient && options.operation !== 'uninstall') {
const clientInstallation = detectedClient ??
detected.get('local') ??
detected.get('cloud') ??
resolveInvokingManager(env);
const sharedClient = await runPackageOperation(clientInstallation, options.operation, [UNIFIED_CLIENT], options.targetLine, runner, env, 'Packages (shared client)', writeLine);
if (!sharedClient.ok) {
writeLine('Mearl setup incomplete. Review the messages above.');
return false;
}
}
for (const profile of selected) {

@@ -194,12 +245,9 @@ const config = MEARL_PROFILES[profile];

}
const packageOperation = options.operation === 'uninstall' ? 'uninstall' : options.operation;
const command = buildGlobalPackageCommand(installation, packageOperation, config.packages, options.targetLine);
writeLine(`Packages (${profile}): ${command.manager}`);
const result = await runLifecycleCommand(runner, command.command, command.args, env, `Packages (${profile})`, writeLine);
if (!result) {
packagesOk = false;
const packageOperation = options.operation;
const packages = config.packages.filter(packageName => packageName !== UNIFIED_CLIENT);
if (packages.length === 0) {
continue;
}
if (result.code !== 0) {
writeLine(`Packages (${profile}): failed (exit ${result.code}).`);
const packageResult = await runPackageOperation(installation, packageOperation, packages, options.targetLine, runner, env, `Packages (${profile})`, writeLine);
if (!packageResult.ok) {
packagesOk = false;

@@ -211,3 +259,3 @@ continue;

const refreshed = detectPackage(config.anchorPackage, config.anchorBins, {
env: prependCommandPath(command.command, env),
env: prependCommandPath(packageResult.command.command, env),
}) ?? current;

@@ -220,2 +268,13 @@ if (!refreshed ||

}
if (selectedUsesClient && options.operation === 'uninstall') {
const remainingClientProfiles = CLIENT_PROFILES.filter(profile => detected.has(profile) && !selected.includes(profile));
if (remainingClientProfiles.length > 0) {
writeLine(`Packages (shared client): kept for ${remainingClientProfiles.join(', ')}.`);
}
else if (packagesOk && detectedClient) {
const sharedClient = await runPackageOperation(detectedClient, 'uninstall', [UNIFIED_CLIENT], undefined, runner, env, 'Packages (shared client)', writeLine);
if (!sharedClient.ok)
packagesOk = false;
}
}
let skillOk = true;

@@ -222,0 +281,0 @@ const selectedUsesSkill = selected.some(profile => MEARL_PROFILES[profile].usesSkill);

@@ -14,5 +14,5 @@ import { detectGlobalPackage } from './packageManager.js';

label: 'cloud agent',
anchorPackage: '@mearl/cloud-client',
anchorBins: ['mearl-cloud'],
packages: ['@mearl/cloud-server', '@mearl/cloud-client'],
anchorPackage: '@mearl/cloud-server',
anchorBins: ['mearl-cloud-server'],
packages: ['@mearl/cloud-server', '@mearl/client'],
usesSkill: true,

@@ -19,0 +19,0 @@ },

{
"name": "@mearl/setup",
"version": "2.5.1",
"version": "2.6.0",
"description": "One-shot environment setup and configuration for Mearl",

@@ -5,0 +5,0 @@ "type": "module",

@@ -6,3 +6,4 @@ # @mearl/setup

```bash
npx @mearl/setup <install|update|uninstall> [--local|--cloud|--mcp] [--yes]
npx @mearl/setup [install] [--local] [--cloud] [--mcp] [--yes]
npx @mearl/setup <update|uninstall> [--local] [--cloud] [--mcp] [--yes]
```

@@ -22,10 +23,15 @@

- `install` 可以省略;直接执行 `npx @mearl/setup` 等同于 `npx @mearl/setup install`。
以选项开头时也默认安装,例如 `npx @mearl/setup --cloud --yes`。
- `install` 未指定环境时默认 `--local`。
- `-h` / `--help` 显示帮助,`-v` / `--version` 显示 setup 版本。
- `update` 和 `uninstall` 未指定环境时,从当前 `PATH` 中的
`mearl-native-host`、`mearl-cloud`、`mearl-mcp-server` 自动检测,可同时处理
`mearl-native-host`、`mearl-cloud-server`、`mearl-mcp-server` 自动检测,可同时处理
多个已安装环境。
- 显式传入 `--local`、`--cloud` 或 `--mcp` 时只处理指定环境。
- `--local`、`--cloud` 与 `--mcp` 可以组合,显式传入时只处理选中的环境。
- 已有环境沿用其原包管理器和全局安装前缀;首次安装沿用启动 setup 的包管理器。
- cloud 环境统一管理 `@mearl/cloud-server` 与 `@mearl/cloud-client`:首次安装后启动
- cloud 环境统一管理 `@mearl/cloud-server` 与 `@mearl/client`:首次安装后启动
Server,更新后仅在 Server 原本运行时重启,卸载前停止。
- local/cloud 共用一份 `@mearl/client`;组合安装只处理一次,卸载单个环境时若另一个环境仍在使用则保留。
- 从 2.5.x 更新 cloud 环境时会先卸载旧 `@mearl/cloud-client`,避免它遗留的 `mearl` bin 与统一 client 冲突。
- local/cloud 共用的全局 mearl skill 通过 `ali-skills` 的 JSON 清单定位,只处理一次。

@@ -60,2 +66,5 @@ - 卸载一个环境但另一个仍依赖全局 mearl skill 时会保留 skill。

# 默认安装本地浏览器环境
npx @mearl/setup
# 与上一条等价
npx @mearl/setup install

@@ -69,2 +78,5 @@

# 同一台机器同时作为本地浏览器宿主和云端 Agent
npx @mearl/setup install --local --cloud
# 自动更新当前 PATH 中检测到的全部 Mearl 环境

@@ -71,0 +83,0 @@ npx @mearl/setup update