@mearl/cloud-server 3.0.0-beta.4 → 3.0.0-beta.7

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
@@ -7,14 +7,10 @@
7
7
  推荐通过 setup 安装完整的云端 Agent 环境(cloud-server、统一 client 与 Agent Skill):
8
8
 
9
9
  ```bash
10
- npx --@mearl:registry=https://registry.npmjs.org @mearl/setup --cloud
10
+ npx @mearl/setup --cloud
11
11
  ```
12
12
 
13
- Qoder Cloud Agent 使用同一套包和 server 命令,只在 setup 时选择配对模式:
14
-
15
- ```bash
16
- npx --@mearl:registry=https://registry.npmjs.org @mearl/setup --qoder-cloud --yes
17
- ```
13
+ 可选连接协议由已安装能力包提供。Qoder 配对见 [`@mearl/plugin-qoder`](../../plugin-qoder/README.md);核心不内置其配对实现。
18
14
 
19
15
  在 Docker 或自定义进程托管等只需要 Server 包的场景,可单独安装 `@mearl/cloud-server`。
20
16
 
@@ -24,8 +20,7 @@ npx --@mearl:registry=https://registry.npmjs.org @mearl/setup --qoder-cloud --ye
24
20
 
25
21
  Server **默认以后台守护进程方式运行**,启动后立即返回,并打印本地机器需要执行的连接命令。
26
22
  POSIX 环境下后台进程会进入独立 session,可在启动命令结束后继续运行。
27
- Qoder 模式保持相同的 `start/status/restart/stop/logs` 交互;`start` 和 `restart` 生成新的
28
- pair/connector 信息后退出,不监听端口或创建守护进程。
23
+ 其他 cloud mode 通过已安装的 `cloud.server.<id>` 加载,未安装时明确失败。
29
24
 
30
25
  ```bash
31
26
  mearl-cloud-server [command] [options]
@@ -75,7 +70,7 @@ mearl-cloud-server --foreground
75
70
  [CloudServer] Logs: ~/.mearl/cloud-server.log
76
71
 
77
72
  Connect from your local machine:
78
- npx --@mearl:registry=https://registry.npmjs.org @mearl/cloud-connector start "ws://10.0.1.100:8080/ws?token=xxx"
73
+ npx @mearl/cloud-connector start "ws://10.0.1.100:8080/ws?token=xxx"
79
74
  ```
80
75
 
81
76
  部署在反向代理或沙箱中时,由部署宿主或 preset 安装器通过 `MEARL_CLOUD_PUBLIC_URL` 提供外部入口,可使用 `{port}` 占位符。核心不探测组织专属沙箱变量或内部端口映射接口;相关自动发现由独立能力包处理。当前阶段尚未接通这些内部适配,内部产品仍保留原实现。
@@ -85,7 +80,7 @@ mearl-cloud-server --foreground
85
80
  运行时文件位于 `~/.mearl/`:
86
81
 
87
82
  - `cloud-server.json` - 连接配置(含 server URL、pid、端口等),统一 `@mearl/client` 自动读取
88
- - `cloud-server-mode.json` - setup 在 Qoder 模式下写入的标识;普通 `--cloud` 会删除它
83
+ - `cloud-server-mode.json` - setup 为可选 cloud mode 写入的标识;普通 `--cloud` 会删除它
89
84
  - `cloud-server.log` - 后台进程日志(`logs` 子命令读取,或 `tail -f` 跟踪);超过 5MB 会在下次启动时滚动为 `cloud-server.log.1`
90
85
 
91
86
  > 守护进程的启停、状态、日志滚动等生命周期逻辑由共享包 [`@mearl/daemon-core`](../../daemon-core) 提供(与 cloud-connector 复用同一套实现)。
@@ -126,9 +121,7 @@ console.log(stats);
126
121
  await server.stop();
127
122
  ```
128
123
 
129
- Qoder 模式只复用 cloud-server CLI 作为建联入口。配对完成后的 action 继续通过 Qoder
130
- Client-Side `mearl` 工具、Session API 和本地 connector 转发,不会连接一个本地
131
- cloud-server 端口。
124
+ 可选 mode 的握手和转发由对应能力包负责。
132
125
 
133
126
  ## 架构
134
127
 
@@ -233,7 +226,7 @@ WantedBy=multi-user.target
233
226
 
234
227
  ```dockerfile
235
228
  FROM node:20-alpine
236
- RUN npm --@mearl:registry=https://registry.npmjs.org install -g @mearl/cloud-server
229
+ RUN npm install -g @mearl/cloud-server
237
230
  EXPOSE 8080
238
231
  CMD ["mearl-cloud-server", "--foreground", "--token", "your-token"]
239
232
  ```
@@ -241,7 +234,7 @@ CMD ["mearl-cloud-server", "--foreground", "--token", "your-token"]
241
234
  ### 使用 PM2
242
235
 
243
236
  ```bash
244
- pm2 start mearl-cloud-server --name mtop-cloud-server -- --foreground --port 8080 --token your-token
237
+ pm2 start mearl-cloud-server --name mearl-cloud-server -- --foreground --port 8080 --token your-token
245
238
  ```
246
239
 
247
240
  ## 注意事项
@@ -28,7 +28,7 @@ function resolveCloudPublicEndpoint(port, env = process.env) {
28
28
  }
29
29
  function formatConnectorCommand(url) {
30
30
  const argument = /[$`"\\\r\n]/.test(url) ? "'" + url.replaceAll("'", "'\\''") + "'" : `"${url}"`;
31
- return `npx --@mearl:registry=https://registry.npmjs.org @mearl/cloud-connector start ${argument}`;
31
+ return `npx @mearl/cloud-connector start ${argument}`;
32
32
  }
33
33
 
34
34
  // src/index.ts
package/dist/cli.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { CloudServerOptions } from './index.js';
2
- import { type CloudServerCommand } from './qoder.js';
2
+ type CloudServerCommand = 'start' | 'stop' | 'restart' | 'status' | 'logs';
3
3
  export interface ParsedCloudServerArgs {
4
4
  command: CloudServerCommand;
5
5
  daemonArgs: string[];
@@ -10,3 +10,4 @@ export interface ParsedCloudServerArgs {
10
10
  }
11
11
  export declare function parseCloudServerArgs(argv: string[]): ParsedCloudServerArgs;
12
12
  export declare function main(argv?: string[]): Promise<number>;
13
+ export {};
package/dist/cli.js CHANGED
@@ -5,9 +5,10 @@ import {
5
5
  LOG_FILE,
6
6
  MODE_FILE,
7
7
  formatConnectorCommand
8
- } from "./chunks/chunk-67UWHFX6.js";
8
+ } from "./chunks/chunk-LXICEBLN.js";
9
9
 
10
10
  // src/cli.ts
11
+ import { capabilityDirectory } from "@mearl/daemon-core/page-runtimes";
11
12
  import { Command, CommanderError, InvalidArgumentError } from "commander";
12
13
 
13
14
  // src/daemon.ts
@@ -82,7 +83,7 @@ import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
82
83
  import { dirname } from "node:path";
83
84
  var CLOUD_SERVER_MODE_ENV = "MEARL_CLOUD_MODE";
84
85
  function isCloudServerMode(value) {
85
- return value === "websocket" || value === "qoder";
86
+ return typeof value === "string" && /^[a-z][a-z0-9-]{0,63}$/.test(value);
86
87
  }
87
88
  function readStoredMode(storage) {
88
89
  const modeFile = storage.modeFile ?? MODE_FILE;
@@ -112,72 +113,18 @@ function resolveCloudServerMode(env = process.env, storage = {}) {
112
113
  const requested = env[CLOUD_SERVER_MODE_ENV];
113
114
  if (requested !== void 0) {
114
115
  if (!isCloudServerMode(requested)) {
115
- throw new Error(`${CLOUD_SERVER_MODE_ENV} must be "websocket" or "qoder"`);
116
+ throw new Error(`${CLOUD_SERVER_MODE_ENV} must be a valid installed cloud mode ID`);
116
117
  }
117
- if (requested === "qoder") writeStoredMode(requested, storage);
118
+ if (requested !== "websocket") writeStoredMode(requested, storage);
118
119
  else clearStoredMode(storage);
119
120
  return requested;
120
121
  }
121
122
  return readStoredMode(storage) ?? "websocket";
122
123
  }
123
124
 
124
- // src/qoder.ts
125
- import { randomBytes } from "node:crypto";
126
- function createQoderPairingInfo(options = {}) {
127
- const pairingCode = (options.createCode ?? (() => randomBytes(24).toString("base64url")))();
128
- if (!/^[A-Za-z0-9_-]{16,128}$/.test(pairingCode)) {
129
- throw new Error("Qoder pairing code must be 16-128 URL-safe characters");
130
- }
131
- const createdAt = (options.now ?? Date.now)();
132
- if (!Number.isSafeInteger(createdAt) || createdAt < 1e12 || createdAt > 9999999999999) {
133
- throw new Error("Qoder pairing timestamp must be a 13-digit epoch millisecond value");
134
- }
135
- return {
136
- pairingCode,
137
- createdAt,
138
- connectorUrl: `qoder://pair/${pairingCode}?created=${createdAt}`,
139
- toolInput: { action: "pair", payload: { code: pairingCode } }
140
- };
141
- }
142
- function formatQoderPairingOutput(info) {
143
- const connectorCommand = `npx --@mearl:registry=https://registry.npmjs.org @mearl/cloud-connector start "${info.connectorUrl}"`;
144
- return `[CloudServer] Qoder pairing mode is ready.
145
-
146
- Connect from your local machine:
147
- ${connectorCommand}
148
-
149
- Then immediately invoke the Qoder client-side custom tool named "mearl" with this input:
150
- ${JSON.stringify(info.toolInput)}
151
-
152
- The connector resolves QODER_PERSONAL_ACCESS_TOKEN from the local environment, ~/.mearl/.env, or supported local credential storage. Never add the PAT to the pairing URL.`;
153
- }
154
- async function runQoderCloudServerCommand(command, dependencies) {
155
- const writeLine = dependencies.writeLine ?? console.log;
156
- switch (command) {
157
- case "start":
158
- case "restart":
159
- if (dependencies.isServerRunning()) await dependencies.stopServer();
160
- writeLine(
161
- formatQoderPairingOutput(
162
- (dependencies.createPairing ?? (() => createQoderPairingInfo()))()
163
- )
164
- );
165
- break;
166
- case "status":
167
- dependencies.printStatus();
168
- writeLine("[CloudServer] Mode: qoder pairing (no listening service)");
169
- break;
170
- case "stop":
171
- await dependencies.stopServer();
172
- break;
173
- case "logs":
174
- dependencies.printLogs();
175
- break;
176
- }
177
- }
178
-
179
125
  // src/cli.ts
180
- var CLOUD_SERVER_VERSION = true ? "3.0.0-beta.4" : "unknown";
126
+ import { NodeCapabilityRegistry } from "@mearl/daemon-core/capabilities";
127
+ var CLOUD_SERVER_VERSION = true ? "3.0.0-beta.7" : "unknown";
181
128
  var COMMANDS = ["start", "stop", "restart", "status", "logs"];
182
129
  var START_OPTION_NAMES = /* @__PURE__ */ new Set([
183
130
  "foreground",
@@ -322,8 +269,11 @@ async function main(argv = process.argv.slice(2)) {
322
269
  return 0;
323
270
  }
324
271
  const mode = resolveCloudServerMode();
325
- if (mode === "qoder") {
326
- await runQoderCloudServerCommand(parsed.command, {
272
+ if (mode !== "websocket") {
273
+ const hook = `cloud.server.${mode}`;
274
+ const registry = new NodeCapabilityRegistry({ version: CLOUD_SERVER_VERSION }, capabilityDirectory(), { hooks: [hook] });
275
+ await registry.refresh();
276
+ await registry.require(hook)(parsed.command, {
327
277
  isServerRunning: isDaemonRunning,
328
278
  stopServer: stopDaemon,
329
279
  printStatus: statusDaemon,
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  CloudServer
3
- } from "./chunks/chunk-67UWHFX6.js";
3
+ } from "./chunks/chunk-LXICEBLN.js";
4
4
  export {
5
5
  CloudServer
6
6
  };
package/dist/mode.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type CloudServerMode = 'websocket' | 'qoder';
1
+ export type CloudServerMode = string;
2
2
  export declare const CLOUD_SERVER_MODE_ENV = "MEARL_CLOUD_MODE";
3
3
  interface CloudServerModeStorage {
4
4
  modeFile?: string;
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@mearl/cloud-server",
3
- "version": "3.0.0-beta.4",
3
+ "version": "3.0.0-beta.7",
4
4
  "description": "Cloud WebSocket server for Mearl — bridges cloud agents to local connectors",
5
5
  "type": "module",
6
6
  "engines": {
7
- "node": ">=22.12.0"
7
+ "node": ">=20.18.0"
8
8
  },
9
9
  "main": "dist/index.js",
10
10
  "types": "dist/index.d.ts",
@@ -33,11 +33,11 @@
33
33
  "registry": "https://registry.npmjs.org"
34
34
  },
35
35
  "dependencies": {
36
- "commander": "^15.0.0",
36
+ "commander": "^14.0.3",
37
37
  "ws": "^8.18.0",
38
- "@mearl/cloud-types": "3.0.0-beta.4",
39
- "@mearl/daemon-core": "3.0.0-beta.4",
40
- "@mearl/client": "3.0.0-beta.4"
38
+ "@mearl/client": "3.0.0-beta.7",
39
+ "@mearl/cloud-types": "3.0.0-beta.7",
40
+ "@mearl/daemon-core": "3.0.0-beta.7"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^24.9.1",
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "repository": {
49
49
  "type": "git",
50
- "url": "git+https://github.com/F-loat/mearl.git",
50
+ "url": "git+https://github.com/mearlhq/mearl.git",
51
51
  "directory": "packages/cloud/cloud-server"
52
52
  },
53
53
  "scripts": {
package/dist/qoder.d.ts DELETED
@@ -1,29 +0,0 @@
1
- export interface QoderPairingInfo {
2
- pairingCode: string;
3
- createdAt: number;
4
- connectorUrl: string;
5
- toolInput: {
6
- action: 'pair';
7
- payload: {
8
- code: string;
9
- };
10
- };
11
- }
12
- export interface QoderPairingOptions {
13
- now?: () => number;
14
- createCode?: () => string;
15
- }
16
- export type CloudServerCommand = 'start' | 'stop' | 'restart' | 'status' | 'logs';
17
- interface QoderCloudServerDependencies {
18
- createPairing?: () => QoderPairingInfo;
19
- isServerRunning: () => boolean;
20
- printLogs: () => void;
21
- printStatus: () => void;
22
- stopServer: () => Promise<void>;
23
- writeLine?: (message: string) => void;
24
- }
25
- /** Create a short-lived correlation handle without embedding Qoder credentials in the URL. */
26
- export declare function createQoderPairingInfo(options?: QoderPairingOptions): QoderPairingInfo;
27
- export declare function formatQoderPairingOutput(info: QoderPairingInfo): string;
28
- export declare function runQoderCloudServerCommand(command: CloudServerCommand, dependencies: QoderCloudServerDependencies): Promise<void>;
29
- export {};