@mearl/cloud-server 3.0.0-beta.8 → 3.0.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.en.md +249 -0
- package/README.md +3 -1
- package/dist/cli.js +1 -1
- package/package.json +5 -4
package/README.en.md
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# @mearl/cloud-server
|
|
2
|
+
|
|
3
|
+
[简体中文](README.md) | [English](README.en.md)
|
|
4
|
+
|
|
5
|
+
A cloud WebSocket server routing cloud Agent requests to local connectors.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Use setup to install a complete cloud Agent environment: cloud-server, the unified client, and Agent Skill.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx @mearl/setup --cloud
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Installed capability packages provide optional connection protocols. See [`@mearl/plugin-qoder`](../../plugin-qoder/README.en.md) for Qoder pairing; the core does not include its pairing implementation.
|
|
16
|
+
|
|
17
|
+
Install `@mearl/cloud-server` separately when only the server package is needed, such as Docker or custom process management.
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
### Command line
|
|
22
|
+
|
|
23
|
+
The server **runs as a background daemon by default**, returns immediately after startup, and prints the connection command to run on the local machine.
|
|
24
|
+
On POSIX systems, the background process enters its own session and continues after the launching command exits.
|
|
25
|
+
Other cloud modes load through installed `cloud.server.<id>` capabilities and fail explicitly if absent.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
mearl-cloud-server [command] [options]
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Subcommands:**
|
|
32
|
+
|
|
33
|
+
- `start` — Start in the background (default when no subcommand is given).
|
|
34
|
+
- `stop` — Stop the background server.
|
|
35
|
+
- `restart` — Restart the background server.
|
|
36
|
+
- `status` — Show status and connection information.
|
|
37
|
+
- `logs` — Print the end of the server log.
|
|
38
|
+
|
|
39
|
+
**Options:**
|
|
40
|
+
|
|
41
|
+
- `--foreground` / `-f` — Run without daemonizing, suitable for systemd / Docker / PM2.
|
|
42
|
+
- `--port <port>` — Server port (default 8080).
|
|
43
|
+
- `--path <path>` — WebSocket path (default /ws).
|
|
44
|
+
- `--token <token>` — Authentication token (generated if omitted).
|
|
45
|
+
- `--heartbeat <seconds>` — Heartbeat timeout (default 90 seconds).
|
|
46
|
+
- `--max-connections <n>` — Maximum connections (default 100).
|
|
47
|
+
|
|
48
|
+
**Examples:**
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Start in background, generate a token, print the connection command, and return
|
|
52
|
+
mearl-cloud-server
|
|
53
|
+
|
|
54
|
+
# Status and connection information
|
|
55
|
+
mearl-cloud-server status
|
|
56
|
+
|
|
57
|
+
# Stop / restart
|
|
58
|
+
mearl-cloud-server stop
|
|
59
|
+
mearl-cloud-server restart
|
|
60
|
+
|
|
61
|
+
# Custom port and authentication
|
|
62
|
+
mearl-cloud-server start --port 9000 --token your-secret-token
|
|
63
|
+
|
|
64
|
+
# Foreground execution for an external process manager
|
|
65
|
+
mearl-cloud-server --foreground
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Background startup prints a connection command for the local machine, for example:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
[CloudServer] Started in background (pid 12345)
|
|
72
|
+
[CloudServer] Logs: ~/.mearl/cloud-server.log
|
|
73
|
+
|
|
74
|
+
Connect from your local machine:
|
|
75
|
+
npx @mearl/cloud-connector start "ws://10.0.1.100:8080/ws?token=xxx"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Behind a reverse proxy or in a sandbox, set `MEARL_CLOUD_PUBLIC_URL` to the external endpoint, optionally using `{port}`. The deployment host or Preset installer provides the connection address.
|
|
79
|
+
|
|
80
|
+
Normal connection commands use double-quoted arguments. When an external path contains shell metacharacters such as `$`, output uses POSIX literal quoting. Run these commands in a POSIX-compatible terminal; other terminals must pass the full publicUrl as one literal argument to `start`.
|
|
81
|
+
|
|
82
|
+
Runtime files live in `~/.mearl/`:
|
|
83
|
+
|
|
84
|
+
- `cloud-server.json` — Connection configuration, including URL, PID, and port; read automatically by `@mearl/client`.
|
|
85
|
+
- `cloud-server-mode.json` — Optional cloud mode marker written by setup; ordinary `--cloud` removes it.
|
|
86
|
+
- `cloud-server.log` — Background log, read with `logs` or `tail -f`; rotates to `cloud-server.log.1` on the next startup if over 5MB.
|
|
87
|
+
|
|
88
|
+
> The shared [`@mearl/daemon-core`](../../daemon-core/README.en.md) supplies lifecycle operations, status, and log rotation, also used by cloud-connector.
|
|
89
|
+
|
|
90
|
+
**Tokens:**
|
|
91
|
+
|
|
92
|
+
- A token is generated when `--token` is omitted. `restart` **preserves the current token**, keeping previously printed connection commands valid.
|
|
93
|
+
- `stop` followed by `start` is a fresh startup and generates a new token. For a stable connection command, supply `--token` or set `MEARL_TOKEN`.
|
|
94
|
+
|
|
95
|
+
**Environment variables:**
|
|
96
|
+
|
|
97
|
+
- `MEARL_TOKEN` — Authentication token, overriding --token.
|
|
98
|
+
- `CLOUD_SERVER_HOST` — Public hostname (automatically detected by default).
|
|
99
|
+
- `MEARL_CLOUD_PUBLIC_URL` — Explicit external endpoint supporting `{port}`. Explicit paths and query parameters are preserved; a root path uses the `path` option. The server sets the authentication token. HTTP/WS endpoints produce `ws://`; HTTPS/WSS endpoints produce `wss://`.
|
|
100
|
+
|
|
101
|
+
### Programmatic usage
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { CloudServer } from '@mearl/cloud-server';
|
|
105
|
+
|
|
106
|
+
const server = new CloudServer({
|
|
107
|
+
port: 8080,
|
|
108
|
+
path: '/ws',
|
|
109
|
+
token: 'your-secret-token',
|
|
110
|
+
heartbeatTimeout: 90,
|
|
111
|
+
maxConnections: 100,
|
|
112
|
+
maxMessageSize: 10 * 1024 * 1024,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
await server.start();
|
|
116
|
+
|
|
117
|
+
// Get statistics
|
|
118
|
+
const stats = server.getStats();
|
|
119
|
+
console.log(stats);
|
|
120
|
+
// { connections: 2, agents: 1, connectors: 1, pendingRequests: 0 }
|
|
121
|
+
|
|
122
|
+
// Graceful shutdown
|
|
123
|
+
await server.stop();
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The corresponding capability package handles handshakes and forwarding for optional modes.
|
|
127
|
+
|
|
128
|
+
## Architecture
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
Cloud Agent
|
|
132
|
+
↓
|
|
133
|
+
@mearl/client
|
|
134
|
+
↓ (WebSocket)
|
|
135
|
+
@mearl/cloud-server (this process)
|
|
136
|
+
↓ (WebSocket)
|
|
137
|
+
@mearl/cloud-connector (local)
|
|
138
|
+
↓ (Unix Socket)
|
|
139
|
+
@mearl/native-host
|
|
140
|
+
↓
|
|
141
|
+
Chrome Extension / CDP
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Connection types
|
|
145
|
+
|
|
146
|
+
The server accepts two connection types:
|
|
147
|
+
|
|
148
|
+
1. **Agent connection** — A cloud client issuing requests.
|
|
149
|
+
2. **Connector connection** — A local connector forwarding requests to native-host.
|
|
150
|
+
|
|
151
|
+
After connecting, clients send `agent_hello` and `connector_hello`, respectively. Connectors register
|
|
152
|
+
a stable ID, name, and version; a reconnection with the same ID replaces the previous connection.
|
|
153
|
+
|
|
154
|
+
With one online Connector, the server selects it automatically. With multiple Connectors, the Agent
|
|
155
|
+
first calls `connector_list`, then passes `connector` with requests. Without an explicit target,
|
|
156
|
+
the server rejects the request to avoid sending browser operations to the wrong machine.
|
|
157
|
+
|
|
158
|
+
## Message protocol
|
|
159
|
+
|
|
160
|
+
### Request format (Agent → Server)
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"id": "unique-id",
|
|
165
|
+
"action": "get_requests",
|
|
166
|
+
"data": { "count": 5 },
|
|
167
|
+
"connector": "work-mac",
|
|
168
|
+
"version": "1.30.0"
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
`connector` accepts an ID or a uniquely matching name. `connector_list` is
|
|
173
|
+
a built-in server command and is not forwarded to the browser.
|
|
174
|
+
|
|
175
|
+
### Response format (Server → Agent)
|
|
176
|
+
|
|
177
|
+
```json
|
|
178
|
+
{
|
|
179
|
+
"id": "unique-id",
|
|
180
|
+
"success": true,
|
|
181
|
+
"data": { ... },
|
|
182
|
+
"versionWarning": "..."
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Heartbeat format
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{ "type": "ping", "timestamp": 1234567890 }
|
|
190
|
+
{ "type": "pong", "timestamp": 1234567890 }
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Authentication
|
|
194
|
+
|
|
195
|
+
When `token` is set, every connection must supply the correct token:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
# Agent connection
|
|
199
|
+
ws://server.com/ws?token=your-secret-token
|
|
200
|
+
|
|
201
|
+
# Connector connection
|
|
202
|
+
ws://server.com/ws?token=your-secret-token
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Deployment recommendations
|
|
206
|
+
|
|
207
|
+
> For systemd / Docker / PM2, add `--foreground` and let the external manager supervise and restart the server.
|
|
208
|
+
|
|
209
|
+
### systemd (Linux)
|
|
210
|
+
|
|
211
|
+
```ini
|
|
212
|
+
[Unit]
|
|
213
|
+
Description=Mearl Cloud Server
|
|
214
|
+
After=network.target
|
|
215
|
+
|
|
216
|
+
[Service]
|
|
217
|
+
Type=simple
|
|
218
|
+
User=your-user
|
|
219
|
+
ExecStart=/usr/bin/mearl-cloud-server --foreground --port 8080 --token your-token
|
|
220
|
+
Restart=always
|
|
221
|
+
RestartSec=5
|
|
222
|
+
|
|
223
|
+
[Install]
|
|
224
|
+
WantedBy=multi-user.target
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Docker
|
|
228
|
+
|
|
229
|
+
```dockerfile
|
|
230
|
+
FROM node:20-alpine
|
|
231
|
+
RUN npm install -g @mearl/cloud-server
|
|
232
|
+
EXPOSE 8080
|
|
233
|
+
CMD ["mearl-cloud-server", "--foreground", "--token", "your-token"]
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### PM2
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
pm2 start mearl-cloud-server --name mearl-cloud-server -- --foreground --port 8080 --token your-token
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Notes
|
|
243
|
+
|
|
244
|
+
- Use WSS (WebSocket Secure) in production for encrypted transport.
|
|
245
|
+
- Use a reverse proxy such as Nginx for WSS upgrades.
|
|
246
|
+
- Set an appropriate `maxConnections` limit to bound resource use.
|
|
247
|
+
- Enable `token` authentication.
|
|
248
|
+
- Sandbox startup automatically detects and uses the platform-assigned public address.
|
|
249
|
+
- If the sandbox port-mapping API is unavailable, it falls back to the local IP address.
|
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# @mearl/cloud-server
|
|
2
2
|
|
|
3
|
+
[简体中文](README.md) | [English](README.en.md)
|
|
4
|
+
|
|
3
5
|
云端 WebSocket Server,用于中转云端 Agent 请求到本地连接器。
|
|
4
6
|
|
|
5
7
|
## 安装
|
|
@@ -83,7 +85,7 @@ mearl-cloud-server --foreground
|
|
|
83
85
|
- `cloud-server-mode.json` - setup 为可选 cloud mode 写入的标识;普通 `--cloud` 会删除它
|
|
84
86
|
- `cloud-server.log` - 后台进程日志(`logs` 子命令读取,或 `tail -f` 跟踪);超过 5MB 会在下次启动时滚动为 `cloud-server.log.1`
|
|
85
87
|
|
|
86
|
-
> 守护进程的启停、状态、日志滚动等生命周期逻辑由共享包 [`@mearl/daemon-core`](../../daemon-core) 提供(与 cloud-connector 复用同一套实现)。
|
|
88
|
+
> 守护进程的启停、状态、日志滚动等生命周期逻辑由共享包 [`@mearl/daemon-core`](../../daemon-core/README.md) 提供(与 cloud-connector 复用同一套实现)。
|
|
87
89
|
|
|
88
90
|
**关于 token:**
|
|
89
91
|
|
package/dist/cli.js
CHANGED
|
@@ -124,7 +124,7 @@ function resolveCloudServerMode(env = process.env, storage = {}) {
|
|
|
124
124
|
|
|
125
125
|
// src/cli.ts
|
|
126
126
|
import { NodeCapabilityRegistry } from "@mearl/daemon-core/capabilities";
|
|
127
|
-
var CLOUD_SERVER_VERSION = true ? "3.0.0
|
|
127
|
+
var CLOUD_SERVER_VERSION = true ? "3.0.0" : "unknown";
|
|
128
128
|
var COMMANDS = ["start", "stop", "restart", "status", "logs"];
|
|
129
129
|
var START_OPTION_NAMES = /* @__PURE__ */ new Set([
|
|
130
130
|
"foreground",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mearl/cloud-server",
|
|
3
|
-
"version": "3.0.0
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Cloud WebSocket server for Mearl — bridges cloud agents to local connectors",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"mearl-cloud-server": "./dist/cli.js"
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
21
|
+
"README.en.md",
|
|
21
22
|
"dist",
|
|
22
23
|
"!dist/**/*.map",
|
|
23
24
|
"!dist/**/__tests__/**",
|
|
@@ -35,9 +36,9 @@
|
|
|
35
36
|
"dependencies": {
|
|
36
37
|
"commander": "^14.0.3",
|
|
37
38
|
"ws": "^8.18.0",
|
|
38
|
-
"@mearl/client": "3.0.0
|
|
39
|
-
"@mearl/cloud-types": "3.0.0
|
|
40
|
-
"@mearl/daemon-core": "3.0.0
|
|
39
|
+
"@mearl/client": "3.0.0",
|
|
40
|
+
"@mearl/cloud-types": "3.0.0",
|
|
41
|
+
"@mearl/daemon-core": "3.0.0"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
44
|
"@types/node": "^24.9.1",
|