@mearl/setup 2.14.0 → 2.15.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/README.md CHANGED
@@ -12,24 +12,17 @@ npx @mearl/setup plugin uninstall <name>
12
12
  npx @mearl/setup provider <install|update|uninstall> <package|id>
13
13
  ```
14
14
 
15
- 配置 AgentBay API Key 时只需执行一次下面的命令,然后在隐藏输入提示中粘贴 Key。
16
- 重复执行会更新现有 Key,并保留 `~/.mearl/.env` 中的其他配置:
17
-
18
- ```bash
19
- npx @mearl/setup agentbay
20
- ```
21
-
22
- 无交互环境可使用 `--stdin` 或 `--key-file <path>`。为避免 Key 进入 shell history 和
23
- 进程参数,不接受把 Key 直接写在命令行中。
15
+ 浏览器 Provider 独立安装和演进。安装后运行 `mearl <providerId>` 查看该版本声明的能力、
16
+ 配置和启动参数。
24
17
 
25
18
  在 Qoder Cloud Agent 环境中,使用 `npx @mearl/setup --qoder-cloud --yes` 选择 Qoder
26
19
  配对模式。它与 `--cloud` 安装同一套 cloud-server、client 和 Skill,只把 cloud-server
27
20
  模式记录为 Qoder;`mearl-cloud-server` 的命令交互保持不变,`start` 和 `restart` 输出新的
28
21
  配对指令后退出,不监听端口或保留守护进程。配对 URL 不包含 Qoder PAT。
29
22
 
30
- ## 安装与注册 Skill CLI 插件
23
+ ## 安装与注册 Skill 插件
31
24
 
32
- 一个命令安装 skill 并注册它的 CLI 能力:
25
+ 一个命令安装 skill 并注册它的 CLI、SDK 和 MCP 能力:
33
26
 
34
27
  ```bash
35
28
  npx @mearl/setup plugin install trip/mearl --skill yuque-doc-fetch --yes
@@ -41,9 +34,14 @@ mearl yuque read "https://aliyuque.antfin.com/group/book/doc"
41
34
  setup 从 `Installed … skill(s)` 成功区块提取路径,仅注册本次安装且包含 `scripts/main.mjs` 的 skill。
42
35
  普通 skill 正常安装。输出格式无法识别时提示手动注册,不扫描其他 skill 或猜测安装结果。
43
36
 
37
+ 默认 `install` 和 `update` 完成后,setup 会用最多 5 秒的 `npm ping` 检查阿里内网 registry。
38
+ 可访问时通过上述 Ali Skills 链路自动安装并注册 `tdbank-account`;该 registry 不用于下载插件。
39
+ 探测不可用或插件安装失败不会破坏 Mearl 主环境的安装;`--skip-skill` 和
40
+ `--target-line` 安装不执行自动插件步骤。
41
+
44
42
  自动注册默认使用安装目录名;入口可用 `export const name = 'yuque'` 指定简短命令名。
45
43
  重装会刷新同名绑定。每个入口必须默认导出 `register(app)`;完整协议见
46
- [CLI 插件规范](../skills/mearl-skill-creator/references/cli-plugin.md)。
44
+ [Skill 插件规范](../skills/mearl-skill-creator/references/cli-plugin.md)。
47
45
 
48
46
  已通过其他渠道分发的 skill 或自定义入口,可以直接传入路径注册:
49
47
 
@@ -57,7 +55,7 @@ path 接受目录或具体文件;目录默认读取 `scripts/main.mjs`,相
57
55
  两种注册流程都会检查本机 `@mearl/client` 和 `@mearl/native-host`:缺失或低于当前 setup 版本时,
58
56
  复用已有包管理器安装 setup 的对应版本,更新后再次验证;更高版本保持不动。
59
57
  native-host 会幂等初始化 Skills 模式。基础环境补齐或初始化失败时保留已安装的 skill,并停止注册。
60
- 注册后可在任意目录运行 `mearl <name> --help`,日常业务调用不执行安装或版本检查。
58
+ 注册后可在任意目录运行 `mearl <name> --help`,也可通过 `@mearl/client` 的 `invokePlugin` 或 MCP 的 `mearl_plugin` 调用;日常业务调用不执行安装或版本检查。
61
59
 
62
60
  不再需要插件时执行:
63
61
 
@@ -211,11 +209,9 @@ npx @mearl/setup uninstall --local
211
209
  # 自动检测并无交互卸载
212
210
  npx @mearl/setup uninstall --yes
213
211
 
214
- # 配置或更新 AgentBay API Key
215
- npx @mearl/setup agentbay
216
-
217
- # 无交互配置(从权限受控的文件读取)
218
- npx @mearl/setup agentbay --key-file ./agentbay.key
212
+ # 安装可选浏览器 Provider
213
+ npx @mearl/setup provider install @ali/mearl-provider-brow
214
+ npx @mearl/setup provider install @ali/mearl-provider-agentbay
219
215
  ```
220
216
 
221
217
  原有 Mearl 环境包的 npm/npx 安装方式和 CLI 保持可用;setup 是统一的便利入口。
package/dist/cli.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { configureAgentBayApiKey, promptAgentBayApiKey, readAgentBayApiKeyFile, readAgentBayApiKeyStdin } from './agentBay.js';
3
2
  import { installMearlBrowserExtension } from './browserExtension.js';
4
3
  import { runMearlLifecycle, type MearlLifecycleOperation } from './lifecycle.js';
5
4
  import type { MearlProfile } from './profiles.js';
@@ -7,13 +6,11 @@ import { installPlugins, setupPlugin, uninstallPlugin } from './plugin.js';
7
6
  import { installProviderPackage, uninstallProviderPackage, updateProviderPackage } from './provider.js';
8
7
  export declare const SETUP_VERSION: string;
9
8
  interface ParsedArgs {
10
- agentBayKeyFile?: string;
11
- agentBayReadStdin: boolean;
12
9
  cloudMode?: 'websocket' | 'qoder';
13
10
  force?: boolean;
14
11
  full?: boolean;
15
12
  help: boolean;
16
- operation?: MearlLifecycleOperation | 'agentbay' | 'extension' | 'plugin' | 'provider';
13
+ operation?: MearlLifecycleOperation | 'extension' | 'plugin' | 'provider';
17
14
  pluginName?: string;
18
15
  pluginPath?: string;
19
16
  pluginInstallArgs?: string[];
@@ -30,10 +27,6 @@ export interface SetupCliDependencies {
30
27
  registerPlugin?: typeof setupPlugin;
31
28
  installPlugins?: typeof installPlugins;
32
29
  uninstallPlugin?: typeof uninstallPlugin;
33
- configureAgentBay?: typeof configureAgentBayApiKey;
34
- promptAgentBayKey?: typeof promptAgentBayApiKey;
35
- readAgentBayKeyFile?: typeof readAgentBayApiKeyFile;
36
- readAgentBayKeyStdin?: typeof readAgentBayApiKeyStdin;
37
30
  installBrowserExtension?: typeof installMearlBrowserExtension;
38
31
  installProvider?: typeof installProviderPackage;
39
32
  runLifecycle?: typeof runMearlLifecycle;
package/dist/cli.js CHANGED
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { Command, CommanderError } from 'commander';
4
- import { configureAgentBayApiKey, promptAgentBayApiKey, readAgentBayApiKeyFile, readAgentBayApiKeyStdin, } from './agentBay.js';
5
4
  import { installMearlBrowserExtension } from './browserExtension.js';
6
5
  import { runMearlLifecycle } from './lifecycle.js';
7
6
  import { isMearlReleaseLine } from './version.js';
@@ -10,7 +9,6 @@ import { installProviderPackage, uninstallProviderPackage, updateProviderPackage
10
9
  const require = createRequire(import.meta.url);
11
10
  export const SETUP_VERSION = require('../package.json').version;
12
11
  const baseParsedArgs = () => ({
13
- agentBayReadStdin: false,
14
12
  help: false,
15
13
  skipSkill: false,
16
14
  yes: false,
@@ -128,31 +126,6 @@ export function parseSetupArgs(argv) {
128
126
  };
129
127
  });
130
128
  program.addCommand(extension);
131
- const agentbay = new Command('agentbay')
132
- .exitOverride()
133
- .configureOutput({ writeErr: () => { }, writeOut: () => { } })
134
- .argument('[api-key]')
135
- .option('--stdin')
136
- .option('--key-file <path>')
137
- .action((apiKey) => {
138
- const options = agentbay.opts();
139
- if (apiKey) {
140
- throw new Error('API keys are not accepted as command-line arguments');
141
- }
142
- if (options.stdin && options.keyFile) {
143
- throw new Error('--stdin and --key-file cannot be used together');
144
- }
145
- if (options.keyFile !== undefined && !options.keyFile.trim()) {
146
- throw new Error('--key-file requires a non-empty path');
147
- }
148
- parsed = {
149
- ...baseParsedArgs(),
150
- ...(options.keyFile ? { agentBayKeyFile: options.keyFile } : {}),
151
- agentBayReadStdin: options.stdin === true,
152
- operation: 'agentbay',
153
- };
154
- });
155
- program.addCommand(agentbay);
156
129
  const normalizedArgv = argv[0] === undefined || argv[0].startsWith('-') ? ['install', ...argv] : argv;
157
130
  try {
158
131
  program.parse(['node', 'mearl-setup', ...normalizedArgv]);
@@ -182,14 +155,12 @@ Usage:
182
155
  npx @mearl/setup plugin install <ali-skills add arguments...>
183
156
  npx @mearl/setup plugin uninstall <name>
184
157
  npx @mearl/setup provider <install|update|uninstall> <package|id>
185
- npx @mearl/setup agentbay [--stdin | --key-file <path>]
186
158
 
187
159
  Behavior:
188
160
  install Default command; defaults to --local when no environment is specified
189
161
  update Auto-detects installed environments from the current PATH
190
162
  uninstall Auto-detects installed environments and asks for confirmation
191
163
  extension Install or update the browser extension; --full also installs the local environment
192
- agentbay Save or update AGENTBAY_KEY without changing other Mearl settings
193
164
  plugin Register, install, or uninstall a CLI plugin
194
165
  provider Install npm Provider packages and manage their Mearl registration
195
166
 
@@ -199,8 +170,6 @@ Options:
199
170
  --qoder-cloud
200
171
  Manage the same cloud packages in Qoder pairing mode
201
172
  --mcp Manage @mearl/mcp-server and its configuration
202
- --stdin Read the AgentBay API key from standard input
203
- --key-file Read the AgentBay API key from a local file
204
173
  --target-line <major.minor.x>
205
174
  Install the latest packages from one release line, such as 2.3.x
206
175
  --skip-skill Keep the independently managed Mearl Skill unchanged
@@ -224,7 +193,7 @@ Examples:
224
193
  npx @mearl/setup extension --full
225
194
  npx @mearl/setup plugin uninstall yuque
226
195
  npx @mearl/setup provider install @ali/mearl-provider-brow
227
- npx @mearl/setup agentbay
196
+ npx @mearl/setup provider install @ali/mearl-provider-agentbay
228
197
  npx @mearl/setup --qoder-cloud --yes
229
198
  npx @mearl/setup update --local --target-line 2.3.x --skip-skill
230
199
  npx @mearl/setup uninstall --local`;
@@ -307,31 +276,6 @@ export async function main(argv = process.argv.slice(2), interactiveTerminal = p
307
276
  return 1;
308
277
  }
309
278
  }
310
- if (parsed.operation === 'agentbay') {
311
- try {
312
- const configureAgentBay = dependencies.configureAgentBay ?? configureAgentBayApiKey;
313
- let apiKey;
314
- if (parsed.agentBayKeyFile) {
315
- apiKey = (dependencies.readAgentBayKeyFile ?? readAgentBayApiKeyFile)(parsed.agentBayKeyFile);
316
- }
317
- else if (parsed.agentBayReadStdin) {
318
- apiKey = await (dependencies.readAgentBayKeyStdin ?? readAgentBayApiKeyStdin)();
319
- }
320
- else {
321
- if (!interactiveTerminal) {
322
- throw new Error('Interactive input is unavailable. Re-run with --stdin or --key-file <path>.');
323
- }
324
- apiKey = await (dependencies.promptAgentBayKey ?? promptAgentBayApiKey)();
325
- }
326
- const result = configureAgentBay(apiKey);
327
- console.error(`AgentBay API key saved to ${result.envFile}.`);
328
- return 0;
329
- }
330
- catch (error) {
331
- console.error(error instanceof Error ? error.message : String(error));
332
- return 1;
333
- }
334
- }
335
279
  if (parsed.operation === 'extension') {
336
280
  if (!interactiveTerminal && !parsed.yes) {
337
281
  console.error('Non-interactive input detected. Re-run with --yes or --non-interactive.');
package/dist/index.d.ts CHANGED
@@ -1,8 +1,6 @@
1
1
  export { buildGlobalPackageCommand, detectGlobalPackage, resolveInvokingPackageManager, resolvePackageManagerInstallation, } from './packageManager.js';
2
- export { configureAgentBayApiKey, promptAgentBayApiKey, readAgentBayApiKeyFile, readAgentBayApiKeyStdin, } from './agentBay.js';
3
2
  export { BrowserExtensionConflictError, extensionArchiveUrl, fetchBrowserExtensionRelease, findLatestExtensionVersion, installMearlBrowserExtension, inspectMearlExtensionViaCdp, loadUnpackedViaCdp, MEARL_EXTENSION_DIRECTORY_NAME, MEARL_EXTENSION_DOWNLOAD_PAGE, MEARL_EXTENSION_ID, MEARL_EXTENSION_REMOTE_CONFIG_URL, resolveChromeUserDataDirectory, resolveMearlExtensionDirectory, updateSetupManagedBrowserExtensionFiles, } from './browserExtension.js';
4
3
  export type { BrowserExtensionDependencies, BrowserExtensionInstallOptions, BrowserExtensionInstallResult, BrowserExtensionRelease, InstalledBrowserExtension, SetupManagedBrowserExtensionUpdateOptions, SetupManagedBrowserExtensionUpdateResult, } from './browserExtension.js';
5
- export type { AgentBayConfigurationOptions, AgentBayConfigurationResult, AgentBaySecretInput, AgentBaySecretOutput, } from './agentBay.js';
6
4
  export type { DetectedGlobalPackage, GlobalPackageCommand, GlobalPackageManager, PackageManagerInstallation, PackageOperation, PackageDetectionOptions, } from './packageManager.js';
7
5
  export { runMearlLifecycle } from './lifecycle.js';
8
6
  export type { MearlLifecycleDependencies, MearlLifecycleOperation, MearlLifecycleOptions, } from './lifecycle.js';
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  export { buildGlobalPackageCommand, detectGlobalPackage, resolveInvokingPackageManager, resolvePackageManagerInstallation, } from './packageManager.js';
2
- export { configureAgentBayApiKey, promptAgentBayApiKey, readAgentBayApiKeyFile, readAgentBayApiKeyStdin, } from './agentBay.js';
3
2
  export { BrowserExtensionConflictError, extensionArchiveUrl, fetchBrowserExtensionRelease, findLatestExtensionVersion, installMearlBrowserExtension, inspectMearlExtensionViaCdp, loadUnpackedViaCdp, MEARL_EXTENSION_DIRECTORY_NAME, MEARL_EXTENSION_DOWNLOAD_PAGE, MEARL_EXTENSION_ID, MEARL_EXTENSION_REMOTE_CONFIG_URL, resolveChromeUserDataDirectory, resolveMearlExtensionDirectory, updateSetupManagedBrowserExtensionFiles, } from './browserExtension.js';
4
3
  export { runMearlLifecycle } from './lifecycle.js';
5
4
  export { MEARL_PROFILES, detectMearlProfiles } from './profiles.js';
@@ -0,0 +1,22 @@
1
+ import { findPluginRegistration } from '@mearl/client/plugin';
2
+ import { installPlugins, uninstallPlugin } from './plugin.js';
3
+ import { findExecutable, type CommandRunner } from './process.js';
4
+ export declare const ALIBABA_NPM_REGISTRY = "https://registry.anpm.alibaba-inc.com/";
5
+ export declare const TDBANK_PLUGIN_INSTALL_ARGS: readonly ["trip/mearl", "--skill", "tdbank-account", "--yes"];
6
+ export declare const INTERNAL_PLUGIN_MANAGER = "@mearl/setup";
7
+ export interface InternalPluginOptions {
8
+ env?: NodeJS.ProcessEnv;
9
+ runCommand?: CommandRunner;
10
+ writeLine?: (line: string) => void;
11
+ }
12
+ export interface InternalPluginDependencies {
13
+ findExecutable?: typeof findExecutable;
14
+ findPluginRegistration?: typeof findPluginRegistration;
15
+ installPlugins?: typeof installPlugins;
16
+ probeAlibabaRegistry?: (options: InternalPluginOptions) => Promise<boolean>;
17
+ uninstallPlugin?: typeof uninstallPlugin;
18
+ }
19
+ export declare function canAccessAlibabaNpmRegistry(options?: InternalPluginOptions, dependencies?: Pick<InternalPluginDependencies, 'findExecutable'>): Promise<boolean>;
20
+ /** Uses the internal registry only as an intranet probe; the plugin is installed by Ali Skills. */
21
+ export declare function installAlibabaInternalPlugins(options?: InternalPluginOptions, dependencies?: InternalPluginDependencies): Promise<'installed' | 'skipped' | 'failed'>;
22
+ export declare function uninstallAlibabaInternalPlugins(options?: InternalPluginOptions, dependencies?: InternalPluginDependencies): Promise<'uninstalled' | 'skipped' | 'failed'>;
@@ -0,0 +1,85 @@
1
+ import { dirname } from 'node:path';
2
+ import { findPluginRegistration } from '@mearl/client/plugin';
3
+ import { installPlugins, uninstallPlugin } from './plugin.js';
4
+ import { findExecutable, prependCommandPath, runCommand } from './process.js';
5
+ export const ALIBABA_NPM_REGISTRY = 'https://registry.anpm.alibaba-inc.com/';
6
+ export const TDBANK_PLUGIN_INSTALL_ARGS = [
7
+ 'trip/mearl',
8
+ '--skill',
9
+ 'tdbank-account',
10
+ '--yes',
11
+ ];
12
+ export const INTERNAL_PLUGIN_MANAGER = '@mearl/setup';
13
+ const TDBANK_PLUGIN_NAME = 'tdbank';
14
+ export async function canAccessAlibabaNpmRegistry(options = {}, dependencies = {}) {
15
+ const env = options.env ?? process.env;
16
+ const runner = options.runCommand ?? runCommand;
17
+ const npm = (dependencies.findExecutable ?? findExecutable)('npm', {
18
+ env,
19
+ extraDirectories: [dirname(process.execPath)],
20
+ });
21
+ if (!npm)
22
+ return false;
23
+ try {
24
+ const result = await runner(npm, [
25
+ 'ping',
26
+ `--registry=${ALIBABA_NPM_REGISTRY}`,
27
+ '--fetch-retries=0',
28
+ '--fetch-timeout=3000',
29
+ '--loglevel=silent',
30
+ ], {
31
+ capture: true,
32
+ env: prependCommandPath(npm, env),
33
+ timeoutMs: 5_000,
34
+ });
35
+ return result.code === 0;
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ }
41
+ /** Uses the internal registry only as an intranet probe; the plugin is installed by Ali Skills. */
42
+ export async function installAlibabaInternalPlugins(options = {}, dependencies = {}) {
43
+ const writeLine = options.writeLine ?? (line => console.error(line));
44
+ try {
45
+ const registration = (dependencies.findPluginRegistration ?? findPluginRegistration)(TDBANK_PLUGIN_NAME);
46
+ if (registration && registration.managedBy !== INTERNAL_PLUGIN_MANAGER) {
47
+ writeLine('TDBank plugin: existing user registration kept.');
48
+ return 'skipped';
49
+ }
50
+ const probe = dependencies.probeAlibabaRegistry ?? (input => canAccessAlibabaNpmRegistry(input));
51
+ if (!(await probe(options)))
52
+ return 'skipped';
53
+ const code = await (dependencies.installPlugins ?? installPlugins)([...TDBANK_PLUGIN_INSTALL_ARGS], options.runCommand, { registrationManagedBy: INTERNAL_PLUGIN_MANAGER });
54
+ if (code !== 0) {
55
+ writeLine(`TDBank plugin: install failed (exit ${code}).`);
56
+ return 'failed';
57
+ }
58
+ writeLine('TDBank plugin: installed and registered.');
59
+ return 'installed';
60
+ }
61
+ catch (error) {
62
+ writeLine(`TDBank plugin: ${error instanceof Error ? error.message : String(error)}; skipped.`);
63
+ return 'failed';
64
+ }
65
+ }
66
+ export async function uninstallAlibabaInternalPlugins(options = {}, dependencies = {}) {
67
+ const writeLine = options.writeLine ?? (line => console.error(line));
68
+ try {
69
+ const registration = (dependencies.findPluginRegistration ?? findPluginRegistration)(TDBANK_PLUGIN_NAME);
70
+ if (registration?.managedBy !== INTERNAL_PLUGIN_MANAGER) {
71
+ if (registration)
72
+ writeLine('TDBank plugin: existing user registration kept.');
73
+ return 'skipped';
74
+ }
75
+ const result = await (dependencies.uninstallPlugin ?? uninstallPlugin)(TDBANK_PLUGIN_NAME, options.runCommand);
76
+ if (!result.removed)
77
+ return 'skipped';
78
+ writeLine('TDBank plugin: uninstalled.');
79
+ return 'uninstalled';
80
+ }
81
+ catch (error) {
82
+ writeLine(`TDBank plugin: ${error instanceof Error ? error.message : String(error)}; uninstall failed.`);
83
+ return 'failed';
84
+ }
85
+ }
@@ -3,6 +3,7 @@ import { detectGlobalPackage, type PackageManagerInstallation } from './packageM
3
3
  import { type DetectedMearlProfiles, type MearlProfile } from './profiles.js';
4
4
  import { uninstallNativeHostArtifacts } from './nativeHost.js';
5
5
  import { type CommandRunner } from './process.js';
6
+ import { installAlibabaInternalPlugins, uninstallAlibabaInternalPlugins } from './internalPlugins.js';
6
7
  export type MearlLifecycleOperation = 'install' | 'update' | 'uninstall';
7
8
  export interface MearlLifecycleOptions {
8
9
  operation: MearlLifecycleOperation;
@@ -21,9 +22,11 @@ export interface MearlLifecycleDependencies {
21
22
  detectPackage?: typeof detectGlobalPackage;
22
23
  detectProfiles?: (env: NodeJS.ProcessEnv) => DetectedMearlProfiles;
23
24
  existsSync?: (filePath: string) => boolean;
25
+ installInternalPlugins?: typeof installAlibabaInternalPlugins;
24
26
  resolveInvokingManager?: (env: NodeJS.ProcessEnv) => PackageManagerInstallation;
25
27
  runCommand?: CommandRunner;
26
28
  runSkillOperation?: typeof runGlobalMearlSkillOperation;
29
+ uninstallInternalPlugins?: typeof uninstallAlibabaInternalPlugins;
27
30
  writeLine?: (line: string) => void;
28
31
  }
29
32
  export declare function runMearlLifecycle(options: MearlLifecycleOptions, dependencies?: MearlLifecycleDependencies): Promise<boolean>;
package/dist/lifecycle.js CHANGED
@@ -8,6 +8,7 @@ import { MEARL_PROFILES, detectMearlProfiles, } from './profiles.js';
8
8
  import { uninstallNativeHostArtifacts } from './nativeHost.js';
9
9
  import { executableNames, prependCommandPath, runCommand, } from './process.js';
10
10
  import { isMearlReleaseLine } from './version.js';
11
+ import { installAlibabaInternalPlugins, uninstallAlibabaInternalPlugins, } from './internalPlugins.js';
11
12
  const LEGACY_CLOUD_CLIENT = '@mearl/cloud-client';
12
13
  const UNIFIED_CLIENT = '@mearl/client';
13
14
  const PROFILE_ORDER = ['local', 'cloud', 'mcp'];
@@ -202,6 +203,9 @@ export async function runMearlLifecycle(options, dependencies = {}) {
202
203
  ? detectPackage(UNIFIED_CLIENT, ['mearl'], { env })
203
204
  : null;
204
205
  const detectedClient = detectedClientCandidate?.packageName === UNIFIED_CLIENT ? detectedClientCandidate : null;
206
+ const remainingClientProfiles = selectedUsesClient && options.operation === 'uninstall'
207
+ ? CLIENT_PROFILES.filter(profile => detected.has(profile) && !selected.includes(profile))
208
+ : [];
205
209
  if (selectedUsesClient && options.operation !== 'uninstall') {
206
210
  const clientInstallation = detectedClient ??
207
211
  detected.get('local') ??
@@ -264,7 +268,6 @@ export async function runMearlLifecycle(options, dependencies = {}) {
264
268
  }
265
269
  }
266
270
  if (selectedUsesClient && options.operation === 'uninstall') {
267
- const remainingClientProfiles = CLIENT_PROFILES.filter(profile => detected.has(profile) && !selected.includes(profile));
268
271
  if (remainingClientProfiles.length > 0) {
269
272
  writeLine(`Packages (shared client): kept for ${remainingClientProfiles.join(', ')}.`);
270
273
  }
@@ -306,7 +309,41 @@ export async function runMearlLifecycle(options, dependencies = {}) {
306
309
  skillOk = false;
307
310
  }
308
311
  }
309
- if (packagesOk && skillOk) {
312
+ let internalPluginsOk = true;
313
+ if (packagesOk && skillOk && selectedUsesClient && options.skipSkill !== true) {
314
+ if (options.operation === 'uninstall') {
315
+ if (remainingClientProfiles.length > 0) {
316
+ writeLine(`TDBank plugin: kept for ${remainingClientProfiles.join(', ')}.`);
317
+ }
318
+ else {
319
+ try {
320
+ internalPluginsOk =
321
+ (await (dependencies.uninstallInternalPlugins ?? uninstallAlibabaInternalPlugins)({
322
+ env,
323
+ runCommand: runner,
324
+ writeLine,
325
+ })) !== 'failed';
326
+ }
327
+ catch (error) {
328
+ writeLine(`TDBank plugin: ${error instanceof Error ? error.message : String(error)}; uninstall failed.`);
329
+ internalPluginsOk = false;
330
+ }
331
+ }
332
+ }
333
+ else if (options.targetLine === undefined) {
334
+ try {
335
+ await (dependencies.installInternalPlugins ?? installAlibabaInternalPlugins)({
336
+ env,
337
+ runCommand: runner,
338
+ writeLine,
339
+ });
340
+ }
341
+ catch (error) {
342
+ writeLine(`TDBank plugin: ${error instanceof Error ? error.message : String(error)}; skipped.`);
343
+ }
344
+ }
345
+ }
346
+ if (packagesOk && skillOk && internalPluginsOk) {
310
347
  writeLine('Mearl setup complete.');
311
348
  return true;
312
349
  }
package/dist/plugin.d.ts CHANGED
@@ -9,4 +9,6 @@ export interface PluginUninstallResult {
9
9
  export declare function uninstallPlugin(name: string, runner?: CommandRunner): Promise<PluginUninstallResult>;
10
10
  /** Ali Skills 的 Installed 区块列出成功路径;计数校验避免输出变化导致漏注册。 */
11
11
  export declare function parseInstalledPluginPaths(output: string): string[];
12
- export declare function installPlugins(args: string[], runner?: CommandRunner): Promise<number>;
12
+ export declare function installPlugins(args: string[], runner?: CommandRunner, options?: {
13
+ registrationManagedBy?: string;
14
+ }): Promise<number>;
package/dist/plugin.js CHANGED
@@ -137,7 +137,7 @@ function permitsEmptyInstallResult(args, output) {
137
137
  args.some(argument => ['--help', '-h', '--list'].includes(argument)) ||
138
138
  /\b(?:installation\s+)?cancel(?:led|ed)\b/i.test(output));
139
139
  }
140
- export async function installPlugins(args, runner = runCommand) {
140
+ export async function installPlugins(args, runner = runCommand, options = {}) {
141
141
  if (args.includes('--')) {
142
142
  throw new Error('plugin install 不支持 -- 参数分隔符,以确保全局 symlink 安装选项生效。');
143
143
  }
@@ -178,7 +178,7 @@ export async function installPlugins(args, runner = runCommand) {
178
178
  }
179
179
  await ensurePluginRuntime(runner);
180
180
  for (const [name, { entry, description }] of plugins) {
181
- registerPlugin(name, entry, description);
181
+ registerPlugin(name, entry, description, { managedBy: options.registrationManagedBy });
182
182
  console.error(`Plugin ${name} registered: ${entry}\nRun: mearl ${name} --help`);
183
183
  }
184
184
  return 0;
package/dist/provider.js CHANGED
@@ -11,9 +11,10 @@ export function parseProviderPackageSpec(value) {
11
11
  }
12
12
  return { packageName: nameMatch[1], target: nameMatch[2] || 'latest' };
13
13
  }
14
- function providerManager(packageName, env, dependencies) {
15
- const resolved = (dependencies.resolveInvokingManager ??
16
- (childEnv => resolveInvokingPackageManager({ env: childEnv })))(env);
14
+ function providerManager(packageName, env, dependencies, resolvedManager) {
15
+ const resolved = resolvedManager ??
16
+ (dependencies.resolveInvokingManager ??
17
+ (childEnv => resolveInvokingPackageManager({ env: childEnv })))(env);
17
18
  if (!packageName.startsWith('@ali/') || resolved.command.includes('tnpm'))
18
19
  return resolved;
19
20
  const tnpm = (dependencies.findExecutable ?? findExecutable)('tnpm', {
@@ -96,7 +97,8 @@ export async function updateProviderPackage(selector, dependencies = {}) {
96
97
  const current = findRegisteredProvider(selector, listProviders);
97
98
  const env = process.env;
98
99
  const runner = dependencies.runCommand ?? runCommand;
99
- const installation = (dependencies.resolvePackageManager ?? resolvePackageManagerInstallation)(current.packageRoot, current.packageName) ?? providerManager(current.packageName, env, dependencies);
100
+ const detectedManager = (dependencies.resolvePackageManager ?? resolvePackageManagerInstallation)(current.packageRoot, current.packageName) ?? undefined;
101
+ const installation = providerManager(current.packageName, env, dependencies, detectedManager);
100
102
  (dependencies.stopProvider ?? stopProvider)(current.providerId);
101
103
  await runPackageCommand(installation, 'update', current.packageName, 'latest', runner, env);
102
104
  const manifest = (dependencies.registerPackage ?? registerProviderPackage)(current.packageRoot);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mearl/setup",
3
- "version": "2.14.0",
3
+ "version": "2.15.0",
4
4
  "description": "One-shot environment setup and configuration for Mearl",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -26,10 +26,6 @@
26
26
  "types": "./dist/nativeHost.d.ts",
27
27
  "import": "./dist/nativeHost.js"
28
28
  },
29
- "./agentbay": {
30
- "types": "./dist/agentBay.d.ts",
31
- "import": "./dist/agentBay.js"
32
- },
33
29
  "./version": {
34
30
  "types": "./dist/version.d.ts",
35
31
  "import": "./dist/version.js"
@@ -65,8 +61,8 @@
65
61
  "commander": "^15.0.0",
66
62
  "extract-zip": "^2.0.1",
67
63
  "ws": "^8.18.3",
68
- "@mearl/client": "2.14.0",
69
- "@mearl/provider": "2.14.0"
64
+ "@mearl/client": "2.15.0",
65
+ "@mearl/provider": "2.15.0"
70
66
  },
71
67
  "devDependencies": {
72
68
  "@types/node": "^24.9.1",
@@ -1,23 +0,0 @@
1
- export interface AgentBayConfigurationOptions {
2
- envFile?: string;
3
- }
4
- export interface AgentBayConfigurationResult {
5
- envFile: string;
6
- updated: boolean;
7
- }
8
- export interface AgentBaySecretInput {
9
- isRaw?: boolean;
10
- isTTY?: boolean;
11
- on(event: 'data', listener: (chunk: Buffer | string) => void): unknown;
12
- pause(): unknown;
13
- removeListener(event: 'data', listener: (chunk: Buffer | string) => void): unknown;
14
- resume(): unknown;
15
- setRawMode?(mode: boolean): unknown;
16
- }
17
- export interface AgentBaySecretOutput {
18
- write(value: string): unknown;
19
- }
20
- export declare function readAgentBayApiKeyFile(file: string): string;
21
- export declare function readAgentBayApiKeyStdin(input?: NodeJS.ReadableStream): Promise<string>;
22
- export declare function promptAgentBayApiKey(input?: AgentBaySecretInput, output?: AgentBaySecretOutput): Promise<string>;
23
- export declare function configureAgentBayApiKey(apiKey: string, options?: AgentBayConfigurationOptions): AgentBayConfigurationResult;
package/dist/agentBay.js DELETED
@@ -1,114 +0,0 @@
1
- import fs from 'node:fs';
2
- import os from 'node:os';
3
- import path from 'node:path';
4
- const AGENTBAY_ENV_KEY = 'AGENTBAY_KEY';
5
- const AGENTBAY_ENV_LINE = /^\s*(?:export\s+)?AGENTBAY_KEY\s*=/;
6
- function normalizeApiKey(apiKey) {
7
- const value = apiKey.trim();
8
- if (!value)
9
- throw new Error('AgentBay API key is required.');
10
- if (/[\r\n\0]/.test(value)) {
11
- throw new Error('AgentBay API key must be a single-line value.');
12
- }
13
- return value;
14
- }
15
- export function readAgentBayApiKeyFile(file) {
16
- const resolved = path.resolve(file);
17
- return normalizeApiKey(fs.readFileSync(resolved, 'utf8'));
18
- }
19
- export async function readAgentBayApiKeyStdin(input = process.stdin) {
20
- let value = '';
21
- for await (const chunk of input)
22
- value += chunk.toString();
23
- return normalizeApiKey(value);
24
- }
25
- export function promptAgentBayApiKey(input = process.stdin, output = process.stderr) {
26
- if (!input.isTTY || !input.setRawMode) {
27
- return Promise.reject(new Error('A TTY is required to enter the AgentBay API key securely.'));
28
- }
29
- const setRawMode = input.setRawMode.bind(input);
30
- return new Promise((resolvePrompt, rejectPrompt) => {
31
- const wasRaw = input.isRaw === true;
32
- let value = '';
33
- let settled = false;
34
- const finish = (error) => {
35
- if (settled)
36
- return;
37
- settled = true;
38
- input.removeListener('data', onData);
39
- setRawMode(wasRaw);
40
- input.pause();
41
- output.write('\n');
42
- if (error)
43
- rejectPrompt(error);
44
- else {
45
- try {
46
- resolvePrompt(normalizeApiKey(value));
47
- }
48
- catch (validationError) {
49
- rejectPrompt(validationError instanceof Error ? validationError : new Error(String(validationError)));
50
- }
51
- }
52
- };
53
- const onData = (chunk) => {
54
- for (const character of chunk.toString()) {
55
- if (character === '\u0003') {
56
- finish(new Error('AgentBay API key input cancelled.'));
57
- return;
58
- }
59
- if (character === '\r' || character === '\n') {
60
- finish();
61
- return;
62
- }
63
- if (character === '\u007f' || character === '\b') {
64
- value = Array.from(value).slice(0, -1).join('');
65
- continue;
66
- }
67
- if (character >= ' ')
68
- value += character;
69
- }
70
- };
71
- output.write('AgentBay API key: ');
72
- setRawMode(true);
73
- input.resume();
74
- input.on('data', onData);
75
- });
76
- }
77
- function updateEnvContent(content, apiKey) {
78
- const newline = content.includes('\r\n') ? '\r\n' : '\n';
79
- const lines = content ? content.split(/\r?\n/) : [];
80
- if (lines.at(-1) === '')
81
- lines.pop();
82
- const entry = `${AGENTBAY_ENV_KEY}=${apiKey}`;
83
- const output = [];
84
- let updated = false;
85
- for (const line of lines) {
86
- if (!AGENTBAY_ENV_LINE.test(line)) {
87
- output.push(line);
88
- continue;
89
- }
90
- if (!updated)
91
- output.push(entry);
92
- updated = true;
93
- }
94
- if (!updated)
95
- output.push(entry);
96
- return { content: `${output.join(newline)}${newline}`, updated };
97
- }
98
- export function configureAgentBayApiKey(apiKey, options = {}) {
99
- const value = normalizeApiKey(apiKey);
100
- const envFile = options.envFile ?? path.join(os.homedir(), '.mearl', '.env');
101
- let current = '';
102
- try {
103
- current = fs.readFileSync(envFile, 'utf8');
104
- }
105
- catch (error) {
106
- if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT'))
107
- throw error;
108
- }
109
- const next = updateEnvContent(current, value);
110
- fs.mkdirSync(path.dirname(envFile), { recursive: true, mode: 0o700 });
111
- fs.writeFileSync(envFile, next.content, { encoding: 'utf8', mode: 0o600 });
112
- fs.chmodSync(envFile, 0o600);
113
- return { envFile, updated: next.updated };
114
- }