@mearl/setup 2.13.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 +14 -18
- package/dist/cli.d.ts +1 -8
- package/dist/cli.js +1 -57
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -1
- package/dist/internalPlugins.d.ts +22 -0
- package/dist/internalPlugins.js +85 -0
- package/dist/lifecycle.d.ts +3 -0
- package/dist/lifecycle.js +39 -2
- package/dist/plugin.d.ts +3 -1
- package/dist/plugin.js +2 -2
- package/dist/provider.js +6 -4
- package/package.json +3 -7
- package/dist/agentBay.d.ts +0 -23
- package/dist/agentBay.js +0 -114
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
|
-
|
|
16
|
-
|
|
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
|
|
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
|
-
[
|
|
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
|
-
#
|
|
215
|
-
npx @mearl/setup
|
|
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 | '
|
|
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
|
+
}
|
package/dist/lifecycle.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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 =
|
|
16
|
-
(
|
|
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
|
|
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.
|
|
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.
|
|
69
|
-
"@mearl/provider": "2.
|
|
64
|
+
"@mearl/client": "2.15.0",
|
|
65
|
+
"@mearl/provider": "2.15.0"
|
|
70
66
|
},
|
|
71
67
|
"devDependencies": {
|
|
72
68
|
"@types/node": "^24.9.1",
|
package/dist/agentBay.d.ts
DELETED
|
@@ -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
|
-
}
|