@mearl/setup 2.4.0 → 2.5.1
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 +19 -1
- package/dist/agentBay.d.ts +23 -0
- package/dist/agentBay.js +114 -0
- package/dist/cli.d.ts +11 -2
- package/dist/cli.js +74 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/lifecycle.js +29 -3
- package/dist/profiles.js +1 -1
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
# @mearl/setup
|
|
2
2
|
|
|
3
|
-
Mearl
|
|
3
|
+
Mearl 环境的一次性安装、更新、卸载与配置工具。无需先全局安装 setup:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npx @mearl/setup <install|update|uninstall> [--local|--cloud|--mcp] [--yes]
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
+
配置 AgentBay API Key 时只需执行一次下面的命令,然后在隐藏输入提示中粘贴 Key。
|
|
10
|
+
重复执行会更新现有 Key,并保留 `~/.mearl/.env` 中的其他配置:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npx @mearl/setup agentbay
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
无交互环境可使用 `--stdin` 或 `--key-file <path>`。为避免 Key 进入 shell history 和
|
|
17
|
+
进程参数,不接受把 Key 直接写在命令行中。
|
|
18
|
+
|
|
9
19
|
## 行为
|
|
10
20
|
|
|
11
21
|
- `install` 未指定环境时默认 `--local`。
|
|
@@ -14,6 +24,8 @@ npx @mearl/setup <install|update|uninstall> [--local|--cloud|--mcp] [--yes]
|
|
|
14
24
|
多个已安装环境。
|
|
15
25
|
- 显式传入 `--local`、`--cloud` 或 `--mcp` 时只处理指定环境。
|
|
16
26
|
- 已有环境沿用其原包管理器和全局安装前缀;首次安装沿用启动 setup 的包管理器。
|
|
27
|
+
- cloud 环境统一管理 `@mearl/cloud-server` 与 `@mearl/cloud-client`:首次安装后启动
|
|
28
|
+
Server,更新后仅在 Server 原本运行时重启,卸载前停止。
|
|
17
29
|
- local/cloud 共用的全局 mearl skill 通过 `ali-skills` 的 JSON 清单定位,只处理一次。
|
|
18
30
|
- 卸载一个环境但另一个仍依赖全局 mearl skill 时会保留 skill。
|
|
19
31
|
- `--mcp` 的客户端配置和清理由 `@mearl/mcp-server` 自己的命令完成。
|
|
@@ -59,6 +71,12 @@ npx @mearl/setup uninstall --local
|
|
|
59
71
|
|
|
60
72
|
# 自动检测并无交互卸载
|
|
61
73
|
npx @mearl/setup uninstall --yes
|
|
74
|
+
|
|
75
|
+
# 配置或更新 AgentBay API Key
|
|
76
|
+
npx @mearl/setup agentbay
|
|
77
|
+
|
|
78
|
+
# 无交互配置(从权限受控的文件读取)
|
|
79
|
+
npx @mearl/setup agentbay --key-file ./agentbay.key
|
|
62
80
|
```
|
|
63
81
|
|
|
64
82
|
原有的 npm/npx 安装方式和各包 CLI 保持可用;setup 只是统一的便利入口。
|
|
@@ -0,0 +1,23 @@
|
|
|
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
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
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
|
+
}
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { configureAgentBayApiKey, promptAgentBayApiKey, readAgentBayApiKeyFile, readAgentBayApiKeyStdin } from './agentBay.js';
|
|
2
3
|
import { type MearlLifecycleOperation } from './lifecycle.js';
|
|
3
4
|
import type { MearlProfile } from './profiles.js';
|
|
4
5
|
interface ParsedArgs {
|
|
6
|
+
agentBayKeyFile?: string;
|
|
7
|
+
agentBayReadStdin: boolean;
|
|
5
8
|
help: boolean;
|
|
6
|
-
operation?: MearlLifecycleOperation;
|
|
9
|
+
operation?: MearlLifecycleOperation | 'agentbay';
|
|
7
10
|
profile?: MearlProfile;
|
|
8
11
|
skipSkill: boolean;
|
|
9
12
|
targetLine?: string;
|
|
10
13
|
yes: boolean;
|
|
11
14
|
}
|
|
15
|
+
export interface SetupCliDependencies {
|
|
16
|
+
configureAgentBay?: typeof configureAgentBayApiKey;
|
|
17
|
+
promptAgentBayKey?: typeof promptAgentBayApiKey;
|
|
18
|
+
readAgentBayKeyFile?: typeof readAgentBayApiKeyFile;
|
|
19
|
+
readAgentBayKeyStdin?: typeof readAgentBayApiKeyStdin;
|
|
20
|
+
}
|
|
12
21
|
export declare function parseSetupArgs(argv: string[]): ParsedArgs;
|
|
13
|
-
export declare function main(argv?: string[], interactiveTerminal?: boolean): Promise<number>;
|
|
22
|
+
export declare function main(argv?: string[], interactiveTerminal?: boolean, dependencies?: SetupCliDependencies): Promise<number>;
|
|
14
23
|
export {};
|
package/dist/cli.js
CHANGED
|
@@ -1,13 +1,45 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { configureAgentBayApiKey, promptAgentBayApiKey, readAgentBayApiKeyFile, readAgentBayApiKeyStdin, } from './agentBay.js';
|
|
4
5
|
import { runMearlLifecycle } from './lifecycle.js';
|
|
5
6
|
import { isMearlReleaseLine } from './version.js';
|
|
6
7
|
export function parseSetupArgs(argv) {
|
|
7
8
|
if (argv.length === 0 || argv.includes('--help') || argv.includes('-h')) {
|
|
8
|
-
return { help: true, skipSkill: false, yes: false };
|
|
9
|
+
return { agentBayReadStdin: false, help: true, skipSkill: false, yes: false };
|
|
9
10
|
}
|
|
10
11
|
const operation = argv[0];
|
|
12
|
+
if (operation === 'agentbay') {
|
|
13
|
+
if (argv.length === 1) {
|
|
14
|
+
return {
|
|
15
|
+
agentBayReadStdin: false,
|
|
16
|
+
help: false,
|
|
17
|
+
operation,
|
|
18
|
+
skipSkill: false,
|
|
19
|
+
yes: false,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
if (argv.length === 2 && argv[1] === '--stdin') {
|
|
23
|
+
return {
|
|
24
|
+
agentBayReadStdin: true,
|
|
25
|
+
help: false,
|
|
26
|
+
operation,
|
|
27
|
+
skipSkill: false,
|
|
28
|
+
yes: false,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (argv.length === 3 && argv[1] === '--key-file' && argv[2]?.trim()) {
|
|
32
|
+
return {
|
|
33
|
+
agentBayKeyFile: argv[2],
|
|
34
|
+
agentBayReadStdin: false,
|
|
35
|
+
help: false,
|
|
36
|
+
operation,
|
|
37
|
+
skipSkill: false,
|
|
38
|
+
yes: false,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
throw new Error('Usage: npx @mearl/setup agentbay [--stdin | --key-file <path>]. API keys are not accepted as command-line arguments.');
|
|
42
|
+
}
|
|
11
43
|
if (operation !== 'install' && operation !== 'update' && operation !== 'uninstall') {
|
|
12
44
|
throw new Error(`Unknown operation: ${operation}`);
|
|
13
45
|
}
|
|
@@ -51,23 +83,35 @@ export function parseSetupArgs(argv) {
|
|
|
51
83
|
if (operation === 'uninstall' && targetLine) {
|
|
52
84
|
throw new Error('--target-line is not available for uninstall');
|
|
53
85
|
}
|
|
54
|
-
return {
|
|
86
|
+
return {
|
|
87
|
+
agentBayReadStdin: false,
|
|
88
|
+
help: false,
|
|
89
|
+
operation,
|
|
90
|
+
profile,
|
|
91
|
+
skipSkill,
|
|
92
|
+
targetLine,
|
|
93
|
+
yes,
|
|
94
|
+
};
|
|
55
95
|
}
|
|
56
96
|
function printHelp() {
|
|
57
97
|
console.error(`Mearl Setup
|
|
58
98
|
|
|
59
99
|
Usage:
|
|
60
100
|
npx @mearl/setup <install|update|uninstall> [--local|--cloud|--mcp] [--yes]
|
|
101
|
+
npx @mearl/setup agentbay [--stdin | --key-file <path>]
|
|
61
102
|
|
|
62
103
|
Behavior:
|
|
63
104
|
install Defaults to --local when no environment is specified
|
|
64
105
|
update Auto-detects installed environments from the current PATH
|
|
65
106
|
uninstall Auto-detects installed environments and asks for confirmation
|
|
107
|
+
agentbay Save or update AGENTBAY_KEY without changing other Mearl settings
|
|
66
108
|
|
|
67
109
|
Options:
|
|
68
110
|
--local Manage @mearl/native-host and @mearl/client
|
|
69
|
-
--cloud Manage @mearl/cloud-client
|
|
111
|
+
--cloud Manage @mearl/cloud-server and @mearl/cloud-client
|
|
70
112
|
--mcp Manage @mearl/mcp-server and its configuration
|
|
113
|
+
--stdin Read the AgentBay API key from standard input
|
|
114
|
+
--key-file Read the AgentBay API key from a local file
|
|
71
115
|
--target-line <major.minor.x>
|
|
72
116
|
Install the latest packages from one release line, such as 2.3.x
|
|
73
117
|
--skip-skill Keep the independently managed Mearl Skill unchanged
|
|
@@ -81,10 +125,11 @@ Examples:
|
|
|
81
125
|
npx @mearl/setup install --yes
|
|
82
126
|
npx @mearl/setup install --cloud
|
|
83
127
|
npx @mearl/setup update
|
|
128
|
+
npx @mearl/setup agentbay
|
|
84
129
|
npx @mearl/setup update --local --target-line 2.3.x --skip-skill
|
|
85
130
|
npx @mearl/setup uninstall --local`);
|
|
86
131
|
}
|
|
87
|
-
export async function main(argv = process.argv.slice(2), interactiveTerminal = process.stdin.isTTY === true && process.stdout.isTTY === true) {
|
|
132
|
+
export async function main(argv = process.argv.slice(2), interactiveTerminal = process.stdin.isTTY === true && process.stdout.isTTY === true, dependencies = {}) {
|
|
88
133
|
let parsed;
|
|
89
134
|
try {
|
|
90
135
|
parsed = parseSetupArgs(argv);
|
|
@@ -98,6 +143,31 @@ export async function main(argv = process.argv.slice(2), interactiveTerminal = p
|
|
|
98
143
|
printHelp();
|
|
99
144
|
return 0;
|
|
100
145
|
}
|
|
146
|
+
if (parsed.operation === 'agentbay') {
|
|
147
|
+
try {
|
|
148
|
+
const configureAgentBay = dependencies.configureAgentBay ?? configureAgentBayApiKey;
|
|
149
|
+
let apiKey;
|
|
150
|
+
if (parsed.agentBayKeyFile) {
|
|
151
|
+
apiKey = (dependencies.readAgentBayKeyFile ?? readAgentBayApiKeyFile)(parsed.agentBayKeyFile);
|
|
152
|
+
}
|
|
153
|
+
else if (parsed.agentBayReadStdin) {
|
|
154
|
+
apiKey = await (dependencies.readAgentBayKeyStdin ?? readAgentBayApiKeyStdin)();
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
if (!interactiveTerminal) {
|
|
158
|
+
throw new Error('Interactive input is unavailable. Re-run with --stdin or --key-file <path>.');
|
|
159
|
+
}
|
|
160
|
+
apiKey = await (dependencies.promptAgentBayKey ?? promptAgentBayApiKey)();
|
|
161
|
+
}
|
|
162
|
+
const result = configureAgentBay(apiKey);
|
|
163
|
+
console.error(`AgentBay API key saved to ${result.envFile}.`);
|
|
164
|
+
return 0;
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
168
|
+
return 1;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
101
171
|
if (!interactiveTerminal && !parsed.yes && parsed.operation !== 'update') {
|
|
102
172
|
console.error('Non-interactive input detected. Re-run with --yes or --non-interactive.');
|
|
103
173
|
return 2;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { buildGlobalPackageCommand, detectGlobalPackage, resolveInvokingPackageManager, resolvePackageManagerInstallation, } from './packageManager.js';
|
|
2
|
+
export { configureAgentBayApiKey, promptAgentBayApiKey, readAgentBayApiKeyFile, readAgentBayApiKeyStdin, } from './agentBay.js';
|
|
3
|
+
export type { AgentBayConfigurationOptions, AgentBayConfigurationResult, AgentBaySecretInput, AgentBaySecretOutput, } from './agentBay.js';
|
|
2
4
|
export type { DetectedGlobalPackage, GlobalPackageCommand, GlobalPackageManager, PackageManagerInstallation, PackageOperation, PackageDetectionOptions, } from './packageManager.js';
|
|
3
5
|
export { runMearlLifecycle } from './lifecycle.js';
|
|
4
6
|
export type { MearlLifecycleDependencies, MearlLifecycleOperation, MearlLifecycleOptions, } from './lifecycle.js';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { buildGlobalPackageCommand, detectGlobalPackage, resolveInvokingPackageManager, resolvePackageManagerInstallation, } from './packageManager.js';
|
|
2
|
+
export { configureAgentBayApiKey, promptAgentBayApiKey, readAgentBayApiKeyFile, readAgentBayApiKeyStdin, } from './agentBay.js';
|
|
2
3
|
export { runMearlLifecycle } from './lifecycle.js';
|
|
3
4
|
export { MEARL_PROFILES, detectMearlProfiles } from './profiles.js';
|
|
4
5
|
export { MEARL_NATIVE_HOST_NAMES, resolveNativeHostDirectory, uninstallNativeHostArtifacts, } from './nativeHost.js';
|
package/dist/lifecycle.js
CHANGED
|
@@ -28,10 +28,10 @@ function siblingExecutable(anchor, name, existsSync) {
|
|
|
28
28
|
}
|
|
29
29
|
return null;
|
|
30
30
|
}
|
|
31
|
-
async function runLifecycleCommand(runner, command, args, env, label, writeLine) {
|
|
31
|
+
async function runLifecycleCommand(runner, command, args, env, label, writeLine, capture = false) {
|
|
32
32
|
try {
|
|
33
33
|
return await runner(command, args, {
|
|
34
|
-
capture
|
|
34
|
+
capture,
|
|
35
35
|
env: prependCommandPath(command, env),
|
|
36
36
|
});
|
|
37
37
|
}
|
|
@@ -59,6 +59,31 @@ async function runHook(profile, operation, detected, runner, existsSync, env, wr
|
|
|
59
59
|
executable = siblingExecutable(detected.executable, 'mearl-mcp-configure', existsSync);
|
|
60
60
|
args = ['--skip-mcp', '--global-install'];
|
|
61
61
|
}
|
|
62
|
+
else if (profile === 'cloud') {
|
|
63
|
+
executable = siblingExecutable(detected.executable, 'mearl-cloud-server', existsSync);
|
|
64
|
+
if (!executable) {
|
|
65
|
+
writeLine(`Hook: ${profile} ${operation} command was not found.`);
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
if (operation === 'uninstall') {
|
|
69
|
+
args = ['stop'];
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const status = await runLifecycleCommand(runner, executable, ['status'], env, 'Hook: cloud status', writeLine, true);
|
|
73
|
+
if (!status)
|
|
74
|
+
return false;
|
|
75
|
+
if (status.code !== 0) {
|
|
76
|
+
writeLine(`Hook: cloud status failed (exit ${status.code}).`);
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
const running = /\[CloudServer\]\s+Status:\s+running\b/.test(status.stdout);
|
|
80
|
+
if (operation === 'update' && !running) {
|
|
81
|
+
writeLine('Hook: cloud update skipped because cloud-server is not running.');
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
args = [running ? 'restart' : 'start'];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
62
87
|
else {
|
|
63
88
|
return true;
|
|
64
89
|
}
|
|
@@ -174,7 +199,8 @@ export async function runMearlLifecycle(options, dependencies = {}) {
|
|
|
174
199
|
packagesOk = false;
|
|
175
200
|
continue;
|
|
176
201
|
}
|
|
177
|
-
if (options.operation !== 'uninstall' &&
|
|
202
|
+
if (options.operation !== 'uninstall' &&
|
|
203
|
+
(profile === 'local' || profile === 'cloud' || profile === 'mcp')) {
|
|
178
204
|
const refreshed = detectPackage(config.anchorPackage, config.anchorBins, {
|
|
179
205
|
env: prependCommandPath(command.command, env),
|
|
180
206
|
}) ?? current;
|
package/dist/profiles.js
CHANGED
|
@@ -13,7 +13,7 @@ export const MEARL_PROFILES = {
|
|
|
13
13
|
label: 'cloud agent',
|
|
14
14
|
anchorPackage: '@mearl/cloud-client',
|
|
15
15
|
anchorBins: ['mearl-cloud'],
|
|
16
|
-
packages: ['@mearl/cloud-client'],
|
|
16
|
+
packages: ['@mearl/cloud-server', '@mearl/cloud-client'],
|
|
17
17
|
usesSkill: true,
|
|
18
18
|
},
|
|
19
19
|
mcp: {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mearl/setup",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "One-shot
|
|
3
|
+
"version": "2.5.1",
|
|
4
|
+
"description": "One-shot environment setup and configuration for Mearl",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -26,6 +26,10 @@
|
|
|
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
|
+
},
|
|
29
33
|
"./version": {
|
|
30
34
|
"types": "./dist/version.d.ts",
|
|
31
35
|
"import": "./dist/version.js"
|