dsh-plugin-mobile-gateway 0.4.1 → 0.5.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/PROTOCOL.md +123 -15
- package/README.md +32 -8
- package/cordis.patch.yml +6 -0
- package/docs/assets/whale-girl-ios-app-promo-16x9.png +0 -0
- package/docs/blog-mobile-gateway.md +542 -0
- package/lib/client.js +31 -9
- package/lib/index.mjs +259 -8
- package/package.json +2 -2
package/PROTOCOL.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# dsh Mobile Gateway — WebSocket 协议参考
|
|
2
2
|
|
|
3
|
-
移动端通过一个经过设备鉴权的 WebSocket 连接与 dsh 通信:订阅 agent
|
|
3
|
+
移动端通过一个经过设备鉴权的 WebSocket 连接与 dsh 通信:订阅 agent 实时输出、发送消息、处理 Human-in-the-loop 提问、查询会话/工作区/历史、调整会话配置。本协议由持久化插件 `dsh-plugin-mobile-gateway` 实现(v0.5.0)。
|
|
4
4
|
|
|
5
5
|
- **本机端点**:`ws://127.0.0.1:3080/ws/mobile`(与 dsh web GUI 同端口)
|
|
6
|
+
- **局域网端点**:`ws://<电脑的私有局域网 IP>:3081/ws/mobile`(插件独立监听,只提供经过鉴权的 WebSocket)
|
|
6
7
|
- **公网端点**:必须由 TLS 反向代理提供 `wss://<域名>/ws/mobile`
|
|
7
8
|
- **帧格式**:全部为 JSON 文本帧(UTF-8)
|
|
8
9
|
- **连接即推送**:连上后服务端立刻发送一条 `hello`,之后 agent 输出以 `event` 帧实时推送
|
|
@@ -43,12 +44,12 @@ WebUI 中有两个互相独立的开关。它们是本机管理设置,iOS 客
|
|
|
43
44
|
|---|---|---|
|
|
44
45
|
| 关闭 | 任意 | WebSocket Upgrade 返回 `503 Service Unavailable` |
|
|
45
46
|
| 开启 | 开启(默认) | 必须使用一次性配对码或长期设备 token,否则返回 `401 Unauthorized` |
|
|
46
|
-
| 开启 | 关闭(仅 Debug) |
|
|
47
|
+
| 开启 | 关闭(仅 Debug) | 仅 DSH 本机监听允许无凭证连接,`hello.authenticated` 为 `false`;独立局域网监听仍返回 `401` |
|
|
47
48
|
|
|
48
49
|
- 移动网关默认关闭。手动开启后,默认 5 分钟内没有客户端成功建立连接就自动关闭。
|
|
49
50
|
- 关闭移动网关会关闭现有连接,WebSocket close code 为 `4004`。
|
|
50
51
|
- 从 Debug 模式重新开启鉴权时,所有无凭证连接会被关闭,close code 为 `4003`。
|
|
51
|
-
- Debug
|
|
52
|
+
- Debug 鉴权开关只影响 DSH 自带的本机监听,并且只在当前 DSH 进程中生效;独立局域网监听始终强制设备鉴权。
|
|
52
53
|
|
|
53
54
|
#### 首次配对
|
|
54
55
|
|
|
@@ -150,7 +151,111 @@ func connectAuthenticated(publicURL: URL, token: String) -> URLSessionWebSocketT
|
|
|
150
151
|
|
|
151
152
|
---
|
|
152
153
|
|
|
153
|
-
## 3.
|
|
154
|
+
## 3. Human-in-the-loop 提问与回答
|
|
155
|
+
|
|
156
|
+
Agent 调用 DSH 的 `ask_user_question` 工具时,插件通过 API Gateway 的 `events.mux()` 收到临时的待回答请求,并推送给移动端。该请求不属于持久化的 `session/event`;回答必须使用本节协议,不能作为普通 `message` 发送。
|
|
157
|
+
|
|
158
|
+
### `question-requested` — 服务端推送问题
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"kind": "question-requested",
|
|
163
|
+
"rpcId": "5ce4f5d1-...",
|
|
164
|
+
"sessionId": "session-abc",
|
|
165
|
+
"questions": [
|
|
166
|
+
{
|
|
167
|
+
"id": "research-direction",
|
|
168
|
+
"header": "研究方向",
|
|
169
|
+
"question": "你想深入研究哪个方向?",
|
|
170
|
+
"detail": "请选择最感兴趣的方向",
|
|
171
|
+
"options": [
|
|
172
|
+
{ "label": "核心架构", "description": "DSH CLI、profile、bundle 与 Cordis" },
|
|
173
|
+
{ "label": "移动网关", "description": "研究 iOS 与 WebSocket 插件" }
|
|
174
|
+
],
|
|
175
|
+
"multiSelect": false
|
|
176
|
+
}
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
- `rpcId`:API Gateway 为这一整批问题生成的稳定 ID。回答或取消时必须原样返回,客户端不得自行生成。
|
|
182
|
+
- `questions`:一次工具调用中的完整问题批次;可能包含多题。
|
|
183
|
+
- `id`:问题 ID,必须在对应答案中原样返回。
|
|
184
|
+
- `header` / `detail`:可选展示信息。
|
|
185
|
+
- `options`:可选列表;每项包含 `label` 和可选 `description`。
|
|
186
|
+
- `multiSelect`:`true` 允许多选,缺省或 `false` 为单选。
|
|
187
|
+
- `intent`:可选展示意图。目前可能为 `{ "kind":"plan-review", "approve":"批准选项标签" }`;未知 intent 应退化为普通选项列表。
|
|
188
|
+
- `replay: true`:可选。表示这是移动端连接后重放的仍待回答问题。iOS 必须按 `rpcId` 去重。
|
|
189
|
+
|
|
190
|
+
### `question-answer` — 移动端提交整批答案
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"type": "question-answer",
|
|
195
|
+
"rpcId": "5ce4f5d1-...",
|
|
196
|
+
"sessionId": "session-abc",
|
|
197
|
+
"answers": [
|
|
198
|
+
{
|
|
199
|
+
"id": "research-direction",
|
|
200
|
+
"selected": ["移动网关"]
|
|
201
|
+
}
|
|
202
|
+
]
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
自由输入使用 `custom`。单选题使用 `custom` 时 `selected` 必须为空;多选题可以同时携带两者:
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
{
|
|
210
|
+
"id": "research-direction",
|
|
211
|
+
"selected": [],
|
|
212
|
+
"custom": "我想研究 API Gateway 的安全边界"
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
提交规则由 API Gateway 严格校验:
|
|
217
|
+
|
|
218
|
+
- 必须一次提交这一批中的全部问题,`answers` 数量、顺序和 `id` 必须与 `questions` 一致。
|
|
219
|
+
- `selected` 中的值必须与原始 `options[].label` 完全一致,且不能重复。
|
|
220
|
+
- 单选题最多选择一项;单选题的 `custom` 与 `selected` 互斥。
|
|
221
|
+
- `custom` 如果存在,去除首尾空白后不能是空字符串。
|
|
222
|
+
|
|
223
|
+
插件立即返回交付回执:
|
|
224
|
+
|
|
225
|
+
```json
|
|
226
|
+
{ "kind":"question-response", "rpcId":"5ce4f5d1-...", "sessionId":"session-abc",
|
|
227
|
+
"action":"answer", "accepted":true }
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
如果 WebUI 或另一台移动设备已经先回答:
|
|
231
|
+
|
|
232
|
+
```json
|
|
233
|
+
{ "kind":"question-response", "rpcId":"5ce4f5d1-...", "sessionId":"session-abc",
|
|
234
|
+
"action":"answer", "accepted":false, "reason":"not-pending" }
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
答案结构不合法时 `reason` 为 `bad-response`。这两种情况均不能重发为普通聊天消息。
|
|
238
|
+
|
|
239
|
+
### `question-cancel` — 跳过/取消整批问题
|
|
240
|
+
|
|
241
|
+
```json
|
|
242
|
+
{ "type":"question-cancel", "rpcId":"5ce4f5d1-...", "sessionId":"session-abc" }
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
回执仍为 `question-response`,其中 `action` 为 `cancel`。取消会让等待中的 `ask_user_question` 以 `ASK_CANCELLED` 结束,iOS 应在用户确认后再执行。
|
|
246
|
+
|
|
247
|
+
### `question-resolved` — 服务端广播最终状态
|
|
248
|
+
|
|
249
|
+
```json
|
|
250
|
+
{ "kind":"question-resolved", "rpcId":"5ce4f5d1-...", "sessionId":"session-abc",
|
|
251
|
+
"outcome":"answered" }
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
`outcome` 为 `answered` 或 `cancelled`。WebUI、iOS 或其他客户端中的第一个合法响应获胜;所有移动连接都会收到最终状态并应关闭对应选择界面。移动端断线重连后,API Gateway 会重放仍待回答的问题;DSH 进程重启则会取消这些仅存在于运行时的问题。
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## 4. 消息(手机 → agent)
|
|
154
259
|
|
|
155
260
|
### `message` — 发送消息(会话不存在则创建)
|
|
156
261
|
```json
|
|
@@ -168,7 +273,7 @@ func connectAuthenticated(publicURL: URL, token: String) -> URLSessionWebSocketT
|
|
|
168
273
|
|
|
169
274
|
---
|
|
170
275
|
|
|
171
|
-
##
|
|
276
|
+
## 5. 会话与历史查询
|
|
172
277
|
|
|
173
278
|
| type | 参数 | 说明 |
|
|
174
279
|
|---|---|---|
|
|
@@ -207,7 +312,7 @@ func connectAuthenticated(publicURL: URL, token: String) -> URLSessionWebSocketT
|
|
|
207
312
|
|
|
208
313
|
---
|
|
209
314
|
|
|
210
|
-
##
|
|
315
|
+
## 6. 工作区与目录
|
|
211
316
|
|
|
212
317
|
| type | 参数 | 说明 |
|
|
213
318
|
|---|---|---|
|
|
@@ -223,7 +328,7 @@ func connectAuthenticated(publicURL: URL, token: String) -> URLSessionWebSocketT
|
|
|
223
328
|
|
|
224
329
|
---
|
|
225
330
|
|
|
226
|
-
##
|
|
331
|
+
## 7. 模型与思考等级
|
|
227
332
|
|
|
228
333
|
| type | 参数 | 说明 |
|
|
229
334
|
|---|---|---|
|
|
@@ -255,7 +360,7 @@ func connectAuthenticated(publicURL: URL, token: String) -> URLSessionWebSocketT
|
|
|
255
360
|
|
|
256
361
|
---
|
|
257
362
|
|
|
258
|
-
##
|
|
363
|
+
## 8. 权限控制
|
|
259
364
|
|
|
260
365
|
| type | 参数 | 说明 |
|
|
261
366
|
|---|---|---|
|
|
@@ -270,7 +375,7 @@ func connectAuthenticated(publicURL: URL, token: String) -> URLSessionWebSocketT
|
|
|
270
375
|
|
|
271
376
|
---
|
|
272
377
|
|
|
273
|
-
##
|
|
378
|
+
## 9. 新会话默认配置
|
|
274
379
|
|
|
275
380
|
| type | 参数 | 说明 |
|
|
276
381
|
|---|---|---|
|
|
@@ -288,7 +393,7 @@ func connectAuthenticated(publicURL: URL, token: String) -> URLSessionWebSocketT
|
|
|
288
393
|
|
|
289
394
|
---
|
|
290
395
|
|
|
291
|
-
##
|
|
396
|
+
## 10. 分支(fork)
|
|
292
397
|
|
|
293
398
|
```json
|
|
294
399
|
{ "type": "fork", "sessionId": "session-abc", "atSeq": 42 }
|
|
@@ -299,7 +404,7 @@ func connectAuthenticated(publicURL: URL, token: String) -> URLSessionWebSocketT
|
|
|
299
404
|
|
|
300
405
|
---
|
|
301
406
|
|
|
302
|
-
##
|
|
407
|
+
## 11. 宿主信息
|
|
303
408
|
|
|
304
409
|
| type | 返回 |
|
|
305
410
|
|---|---|
|
|
@@ -313,13 +418,14 @@ func connectAuthenticated(publicURL: URL, token: String) -> URLSessionWebSocketT
|
|
|
313
418
|
|
|
314
419
|
---
|
|
315
420
|
|
|
316
|
-
##
|
|
421
|
+
## 12. 服务端主动推送
|
|
317
422
|
|
|
318
423
|
| kind | 触发时机 |
|
|
319
424
|
|---|---|
|
|
320
425
|
| `paired` | 首次配对成功;仅此一次返回长期设备 token |
|
|
321
426
|
| `hello` | 连接成功:`{ "kind":"hello", "protocol":2, "authenticated":true, "port":3080, "clients":1 }` |
|
|
322
427
|
| `event` | 任意会话的 agent 输出(见下) |
|
|
428
|
+
| `question-requested` / `question-resolved` | Human-in-the-loop 问题请求与最终状态 |
|
|
323
429
|
| `pong` / `subscribed` / `sent` | 对应请求的回复 |
|
|
324
430
|
|
|
325
431
|
### `event` 帧(agent 实时输出)
|
|
@@ -337,7 +443,7 @@ func connectAuthenticated(publicURL: URL, token: String) -> URLSessionWebSocketT
|
|
|
337
443
|
|
|
338
444
|
---
|
|
339
445
|
|
|
340
|
-
##
|
|
446
|
+
## 13. 端到端示例(Postman)
|
|
341
447
|
|
|
342
448
|
1. Connect → 收到 `hello`
|
|
343
449
|
2. `{"type":"sessions"}` → 挑 `sessionId`(或直接下一步自动建)
|
|
@@ -350,7 +456,7 @@ func connectAuthenticated(publicURL: URL, token: String) -> URLSessionWebSocketT
|
|
|
350
456
|
|
|
351
457
|
---
|
|
352
458
|
|
|
353
|
-
##
|
|
459
|
+
## 14. 安全注意
|
|
354
460
|
|
|
355
461
|
- `/ws/mobile` 的移动网关默认关闭;本机 WebUI 手动开启后,若 5 分钟内没有设备成功连接会自动关闭
|
|
356
462
|
- 网关开启后仍要求已配对设备凭证;不要把 `requireAuth` 设为 `false` 后暴露到网络
|
|
@@ -358,10 +464,11 @@ func connectAuthenticated(publicURL: URL, token: String) -> URLSessionWebSocketT
|
|
|
358
464
|
- DSH HTTP Server 本身没有 TLS、认证或 Origin policy;公网必须使用 TLS 反向代理和 `wss://`
|
|
359
465
|
- 长期 token 只保存在 iOS Keychain;服务端磁盘仅保存摘要
|
|
360
466
|
- `set-default` / `save-default-model` 是全局写操作,客户端 UI 应加确认
|
|
467
|
+
- `question-answer` / `question-cancel` 会直接恢复或终止等待中的 Agent 工具调用;只允许经过鉴权的可信设备提交,并按 `rpcId` 防止重复操作
|
|
361
468
|
|
|
362
469
|
---
|
|
363
470
|
|
|
364
|
-
##
|
|
471
|
+
## 15. 版本历史(插件)
|
|
365
472
|
|
|
366
473
|
| 版本 | 新增 |
|
|
367
474
|
|---|---|
|
|
@@ -379,6 +486,7 @@ func connectAuthenticated(publicURL: URL, token: String) -> URLSessionWebSocketT
|
|
|
379
486
|
| v0.1.16 | fork(新对话分支) |
|
|
380
487
|
| v0.1.17 | models 支持无 sessionId 全局目录;新增 providers |
|
|
381
488
|
| v0.3.0 | 默认设备鉴权;一次性二维码配对;摘要化凭证存储;WebUI 设备面板;在线状态和即时吊销 |
|
|
489
|
+
| v0.5.0 | Human-in-the-loop:转发 API Gateway question 请求、整批回答/取消、重连重放与多端状态收敛 |
|
|
382
490
|
|
|
383
491
|
---
|
|
384
492
|
|
package/README.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/assets/whale-girl-ios-app-promo-16x9.png" alt="鲸鱼娘展示 DeepSeek Harness Mobile 与移动网关" width="100%">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
1
5
|
# dsh-plugin-mobile-gateway
|
|
2
6
|
|
|
3
|
-
为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 提供经过设备鉴权的持久化 WebSocket 网关,让 iOS 等移动客户端能够查看工作区和历史会话、接收 Agent
|
|
7
|
+
为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 提供经过设备鉴权的持久化 WebSocket 网关,让 iOS 等移动客户端能够查看工作区和历史会话、接收 Agent 实时输出、处理 Human-in-the-loop 选择、发送任务,以及调整会话模型与权限。
|
|
4
8
|
|
|
5
9
|

|
|
6
10
|
|
|
@@ -24,7 +28,7 @@ dsh plugin --profile web add dsh-plugin-mobile-gateway
|
|
|
24
28
|
如果希望固定版本,可以在包名后指定版本号:
|
|
25
29
|
|
|
26
30
|
```bash
|
|
27
|
-
dsh plugin --profile web add dsh-plugin-mobile-gateway@0.
|
|
31
|
+
dsh plugin --profile web add dsh-plugin-mobile-gateway@0.5.0
|
|
28
32
|
```
|
|
29
33
|
|
|
30
34
|
也可以不经过 npm,直接安装 GitHub 版本:
|
|
@@ -45,7 +49,19 @@ dsh --profile web --dump-config | grep -A3 mobile-gateway
|
|
|
45
49
|
|
|
46
50
|
启动 WebUI 后,左侧边栏底部应出现“移动设备”入口。
|
|
47
51
|
|
|
48
|
-
### 3.
|
|
52
|
+
### 3. 局域网直接连接(无需域名、证书或反向代理)
|
|
53
|
+
|
|
54
|
+
插件安装并重启 `dsh web` 后,会额外创建一个仅用于移动端的局域网监听:
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
ws://<运行 DSH 的电脑局域网 IP>:3081/ws/mobile
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
打开 WebUI 的“移动设备”面板时,插件会自动检测电脑的私有 IPv4,并优先把可用地址填入“WebSocket 地址”。开启移动网关、生成二维码并用 iOS 客户端扫码即可。电脑和手机需要位于可互访的同一局域网;如果系统防火墙询问是否允许 Node 接收入站连接,请允许私有网络访问 TCP `3081`。
|
|
61
|
+
|
|
62
|
+
该端口只接受来自本机或私有网络地址的 `/ws/mobile` WebSocket Upgrade,不提供 WebUI,也不暴露 `/mgw/*` 管理接口。局域网监听始终要求设备配对鉴权,WebUI 中的 Debug 鉴权开关不会关闭它的鉴权。
|
|
63
|
+
|
|
64
|
+
### 4. 一条命令配置公网 IP(推荐,无需域名)
|
|
49
65
|
|
|
50
66
|
如果 Harness 部署在带固定公网 IPv4 的腾讯云 Ubuntu/Debian 服务器上,先在腾讯云安全组中放行入站 TCP `80` 和 `443`,然后在服务器执行:
|
|
51
67
|
|
|
@@ -90,7 +106,7 @@ sudo npx --yes dsh-plugin-mobile-gateway remove
|
|
|
90
106
|
|
|
91
107
|
1. 开启“允许移动设备连接”。
|
|
92
108
|
2. 保持“设备鉴权”开启。
|
|
93
|
-
3.
|
|
109
|
+
3. 在“WebSocket 地址”中填写手机可以访问的地址。
|
|
94
110
|
|
|
95
111
|
本机浏览器调试可以使用:
|
|
96
112
|
|
|
@@ -98,15 +114,15 @@ sudo npx --yes dsh-plugin-mobile-gateway remove
|
|
|
98
114
|
ws://127.0.0.1:3080/ws/mobile
|
|
99
115
|
```
|
|
100
116
|
|
|
101
|
-
真机不能使用 `127.0.0.1
|
|
117
|
+
真机不能使用 `127.0.0.1`,因为它在手机上指向手机自身。同一私有局域网可使用插件自动提供的 `ws://局域网IP:3081/ws/mobile`;公网连接则应通过 TLS 反向代理提供:
|
|
102
118
|
|
|
103
119
|
```text
|
|
104
120
|
wss://gateway.example.com/ws/mobile
|
|
105
121
|
```
|
|
106
122
|
|
|
107
|
-
|
|
123
|
+
只有 localhost、`.local` 主机名及 RFC 1918/链路本地私有地址允许使用 `ws://`。其他地址会强制要求 `wss://`,以免一次性配对信息和长期连接暴露在公网明文网络中。
|
|
108
124
|
|
|
109
|
-
###
|
|
125
|
+
### 5. 配对 iOS 客户端
|
|
110
126
|
|
|
111
127
|
1. 在 WebUI 中填写设备名称,例如 `iPhone`。
|
|
112
128
|
2. 点击“生成配对二维码”。
|
|
@@ -196,6 +212,10 @@ TLS 证书、域名、防火墙、访问日志保护和代理层速率限制由
|
|
|
196
212
|
gatewayWaitTimeoutMs: 300000
|
|
197
213
|
requireAuth: true
|
|
198
214
|
adminLoopbackOnly: true
|
|
215
|
+
lanEnabled: true
|
|
216
|
+
lanHost: 0.0.0.0
|
|
217
|
+
lanPort: 3081
|
|
218
|
+
lanAdvertiseHost: ''
|
|
199
219
|
publicUrl: wss://gateway.example.com/ws/mobile
|
|
200
220
|
publicUrlFile: /etc/dsh-mobile-gateway/public-url
|
|
201
221
|
pairingTtlMs: 300000
|
|
@@ -211,7 +231,8 @@ TLS 证书、域名、防火墙、访问日志保护和代理层速率限制由
|
|
|
211
231
|
| WebUI 没有“移动设备”入口 | 确认使用 `--profile web` 安装;执行 `--dump-config` 检查组合树,然后完整重启 `dsh web` |
|
|
212
232
|
| iOS 连接提示 `503` | 移动网关尚未开启,回到 WebUI 开启“允许移动设备连接” |
|
|
213
233
|
| iOS 连接提示 `401` | 配对码过期、长期凭证无效或设备已被吊销;删除客户端旧凭证后重新配对 |
|
|
214
|
-
| 真机无法连接 `127.0.0.1` | `127.0.0.1`
|
|
234
|
+
| 真机无法连接 `127.0.0.1` | `127.0.0.1` 在手机上不是电脑;局域网使用面板自动显示的 `ws://私有IP:3081/ws/mobile`,公网使用 `wss://` 地址 |
|
|
235
|
+
| 同一 Wi-Fi 仍无法连接局域网地址 | 确认手机与电脑所在网络允许设备互访,并放行电脑入站 TCP 3081;访客 Wi-Fi 通常会启用客户端隔离 |
|
|
215
236
|
| 一键配置无法识别公网 IP | 确认命令运行在腾讯云 CVM 内,或通过 `--ip <公网 IPv4>` 显式指定 |
|
|
216
237
|
| Certbot 申请或续期失败 | 确认腾讯云安全组和服务器防火墙都允许入站 TCP 80/443,并确认公网 IP 没有变化 |
|
|
217
238
|
| 想检查自动续期 | 执行 `sudo systemctl status dsh-mobile-gateway-cert-renew.timer` 和 `sudo npx --yes dsh-plugin-mobile-gateway status` |
|
|
@@ -247,6 +268,9 @@ NODE_PATH=/path/to/dsh/node_modules node test/gateway.test.mjs
|
|
|
247
268
|
|
|
248
269
|
# 公网 IP 安装器的参数、Nginx 隔离与续期配置
|
|
249
270
|
node test/setup-ip.test.mjs
|
|
271
|
+
|
|
272
|
+
# 独立局域网监听、强制鉴权与管理接口隔离
|
|
273
|
+
node test/lan.test.mjs
|
|
250
274
|
```
|
|
251
275
|
|
|
252
276
|
版本历史与全部 WebSocket 消息类型见 [`PROTOCOL.md`](PROTOCOL.md)。
|
package/cordis.patch.yml
CHANGED
|
@@ -13,6 +13,12 @@
|
|
|
13
13
|
requireAuth: true
|
|
14
14
|
adminLoopbackOnly: true
|
|
15
15
|
pairingTtlMs: 300000
|
|
16
|
+
# DSH WebUI remains loopback-only on 3080. The plugin owns this
|
|
17
|
+
# authenticated, WebSocket-only LAN listener for phones on the same
|
|
18
|
+
# private network.
|
|
19
|
+
lanEnabled: true
|
|
20
|
+
lanHost: 0.0.0.0
|
|
21
|
+
lanPort: 3081
|
|
16
22
|
# Written automatically by `sudo npx dsh-plugin-mobile-gateway setup`.
|
|
17
23
|
publicUrlFile: /etc/dsh-mobile-gateway/public-url
|
|
18
24
|
|
|
Binary file
|