dsh-lan-relay 0.0.0-stage → 1.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/LICENSE +21 -0
- package/README.md +222 -2
- package/client.js +1566 -0
- package/cordis.patch.yml +8 -0
- package/docs/MIGRATION-0.4-to-1.0.md +80 -0
- package/docs/TWO-MACHINE-SETUP.md +62 -0
- package/examples/config.hub.json +24 -0
- package/examples/config.peer.json +24 -0
- package/examples/mcp-connector.json +13 -0
- package/examples/skill-lan-relay/SKILL.md +59 -0
- package/hub.mjs +187 -0
- package/icon.svg +14 -0
- package/index.js +874 -0
- package/lib/config.mjs +121 -0
- package/lib/core.mjs +707 -0
- package/lib/hub-server.mjs +571 -0
- package/lib/join-code.mjs +125 -0
- package/lib/plugin-config.mjs +242 -0
- package/lib/relay-client.mjs +265 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/mcp-server.mjs +284 -0
- package/package.json +86 -4
- package/relay-cli.mjs +169 -0
- package/scripts/allow-firewall.ps1 +55 -0
- package/scripts/install-autostart.ps1 +282 -0
- package/scripts/setup.ps1 +231 -0
- package/start-hub.cmd +13 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ready-player-zero (ZERO)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,223 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-lan-relay
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **标准 DeepSeek Harness(DSH)插件**:让**局域网内多台机器上的 DSH Agent 互相通信**。
|
|
4
|
+
> 一个包、一次安装、一个设置页:一台机器在 DSH 进程内当 hub,其余机器粘贴**加入码**即可加入;
|
|
5
|
+
> 消息离线补投,收到消息可**自动唤醒**目标会话。不需要单独的 hub 进程、不需要 MCP 连接器、不需要计划任务。
|
|
6
|
+
>
|
|
7
|
+
> **版本** v1.0.0 · **License** MIT · **Node** ≥ 18(随 DSH 运行时提供) · **DSH** ≥ 0.2.1-rc.2
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. 它解决什么
|
|
12
|
+
|
|
13
|
+
| 场景 | 用什么 |
|
|
14
|
+
|---|---|
|
|
15
|
+
| 同一台机器、同一个 DSH 里的多 Agent 协作 | 内置 **Agent Teams**(`spawn_teammate` / `send_message` / 任务板),不需要本项目 |
|
|
16
|
+
| **不同机器**上的 DSH Agent 互相发消息、等回复、跨机器唤醒 | **本项目** |
|
|
17
|
+
|
|
18
|
+
内置 Agent Teams 不跨进程/跨主机;dsh-lan-relay 补的就是这个缺口。
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 2. 一键安装(推荐路径)
|
|
23
|
+
|
|
24
|
+
1. DSH 侧边栏 → **插件(Plugins)** → **添加插件** → 输入包名 `dsh-lan-relay`(npm 发布后),或 Git 地址 / 本地目录。
|
|
25
|
+
2. 打开 **设置 → 局域网中继**:
|
|
26
|
+
- 选一台机器当服务端:**运行角色 → 服务端 → 保存**。插件会在 DSH 进程内启动 hub、自动生成 token 和**加入码**。
|
|
27
|
+
- 其他机器:**运行角色 → 客户端**,把服务端页面上的**加入码**粘贴进来 → **保存**。
|
|
28
|
+
3. (仅当 Windows 防火墙开着)在服务端页面点 **一键放行防火墙**,在弹出的 UAC 里点「是」;也可以手动执行页面给出的命令。
|
|
29
|
+
|
|
30
|
+
完成后:设置页顶部显示「服务端运行中 / 客户端已连接」,`在线 peer` 里能看到对方机器。
|
|
31
|
+
**hub 与轮询都在 DSH 进程内**,随 DSH 启动/退出,没有额外进程和自启项。
|
|
32
|
+
|
|
33
|
+
> **不想点界面?** 也可以直接在会话里让 Agent 配置,例如
|
|
34
|
+
> 「把本机设成局域网中继的服务端」「用这个加入码加入:dshrelay1.…」——
|
|
35
|
+
> 插件提供了 `lan_relay_configure` 工具,和设置页写的是同一份配置。
|
|
36
|
+
> (DS Bot 等自定义侧边栏模式里设置页入口可能被替换,用这个方式最省事。)
|
|
37
|
+
|
|
38
|
+
> 当前仓库的安装(未发布 npm 时):
|
|
39
|
+
> ```powershell
|
|
40
|
+
> dsh plugin --profile desktop add "D:\path\to\dsh-lan-relay"
|
|
41
|
+
> # 或让 Agent 用 plugin_manager install_bundle 安装这个目录
|
|
42
|
+
> ```
|
|
43
|
+
> 发布到 npm 后就是上面的「输入包名」一步。
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 3. 架构(一个包,两半)
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
机器 A(服务端) 机器 B(客户端)
|
|
51
|
+
┌──────────────────────────────────────────┐ ┌──────────────────────────────────────────┐
|
|
52
|
+
│ DSH 进程 │ │ DSH 进程 │
|
|
53
|
+
│ ┌─ Host 半(index.js)────────────────┐ │ │ ┌─ Host 半(index.js)────────────────┐ │
|
|
54
|
+
│ │ 内嵌 hub :8787(0.0.0.0) │ │ │ │ 中继客户端(HTTP 长轮询) │ │
|
|
55
|
+
│ │ 中继客户端(127.0.0.1:8787) │◄─┼────┼──┤ 6 个 Agent 工具 │ │
|
|
56
|
+
│ │ 6 个 Agent 工具 + 自动唤醒 │ │ │ │ 自动唤醒 │ │
|
|
57
|
+
│ │ /lan-relay/api/*(仅回环,给设置页) │ │ │ │ /lan-relay/api/* │ │
|
|
58
|
+
│ └──────────────────────────────────────┘ │ │ └──────────────────────────────────────┘ │
|
|
59
|
+
│ ┌─ Web 半(client.js)─────────────────┐ │ │ ┌─ Web 半(client.js)─────────────────┐ │
|
|
60
|
+
│ │ 设置 → 局域网中继(角色/端口/token/ │ │ │ │ 同一页面:粘贴加入码加入 │ │
|
|
61
|
+
│ │ 加入码/在线 peer/防火墙) │ │ │ │ │ │
|
|
62
|
+
│ └──────────────────────────────────────┘ │ │ └──────────────────────────────────────┘ │
|
|
63
|
+
└──────────────────────────────────────────┘ └──────────────────────────────────────────┘
|
|
64
|
+
▲ ▲
|
|
65
|
+
└──────────── 明文 HTTP + x-relay-token ────┘
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- **Host 半**:读 `~/.dsh/lan-relay/config.json`,按 `role` 启/停内嵌 hub、注册工具、后台长轮询并唤醒会话,并给设置页提供同源管理 API。
|
|
69
|
+
- **Web 半**:只负责「设置 → 局域网中继」这一页,所有写入都通过 Host 半的 `/lan-relay/api/*`。
|
|
70
|
+
- 配置文件与旧版 hub / MCP server / CLI **完全兼容**,只是多了 `role` 字段。
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 4. 配置(`~/.dsh/lan-relay/config.json`)
|
|
75
|
+
|
|
76
|
+
一般不用手改,设置页会写它;排查或脚本化时可以直接编辑(改完在设置页点一次「刷新」,或重启 DSH)。
|
|
77
|
+
|
|
78
|
+
| 字段 | 默认 | 说明 |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| `role` | 自动推断 | `server` / `client` / `off`。未设置时:有 `hub.enabled:true` → server;有 token+地址 → client;否则 off |
|
|
81
|
+
| `self` | 主机名 | 本机 peer 名(小写字母/数字/`._-`,≤32);对端用它发消息给你 |
|
|
82
|
+
| `relay_url` | — | 客户端要连的 hub 地址,如 `http://192.168.0.105:8787`;服务端会自动写成 `http://127.0.0.1:<port>` |
|
|
83
|
+
| `token` | 服务端自动生成 | 两台机器必须一致;服务端首次启用时生成并落盘 |
|
|
84
|
+
| `hub.host` / `hub.port` | `0.0.0.0` / `8787` | 服务端监听地址与端口 |
|
|
85
|
+
| `hub.data_dir` | `~/.dsh/lan-relay/hub` | 消息落盘目录(`messages.jsonl`,最多 5000 条 / 8MB 轮转) |
|
|
86
|
+
| `state_dir` | `~/.dsh/lan-relay/state` | 游标、调试日志 |
|
|
87
|
+
| `push.enabled` | `true` | 是否后台长轮询并自动唤醒 |
|
|
88
|
+
| `push.wake` | `true` | `false` = 只注入背景,不主动跑一轮 |
|
|
89
|
+
| `push.default_session` | `""` | 没有指定 `to_session` 的消息投给哪个会话;留空投最近活跃会话 |
|
|
90
|
+
| `push.poll_timeout_seconds` | `25` | 每轮长轮询秒数 |
|
|
91
|
+
| `push.cold_session` | `prompt` | 目标会话未打开时:`prompt` 用 `sessionController.prompt()` 自动 resume 并投递;`drop` 放弃 |
|
|
92
|
+
| `push.offline_fallback` | `false` | 冷启动失败后是否改投其它活跃会话 |
|
|
93
|
+
| `push.require_session` | `false` | `true` 时拒收没有 `to_session` 的消息 |
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 5. Agent 工具
|
|
98
|
+
|
|
99
|
+
装好插件后,Agent 直接可用(不需要 MCP 连接器):
|
|
100
|
+
|
|
101
|
+
| 工具 | 作用 |
|
|
102
|
+
|---|---|
|
|
103
|
+
| `lan_relay_send` | 给另一台机器发消息:`to`(peer 名或 `"*"`)、`text`、可选 `to_session` / `thread` |
|
|
104
|
+
| `lan_relay_inbox` | 拉取新消息(推进游标;`from_seq=0` 重读历史) |
|
|
105
|
+
| `lan_relay_wait` | 长轮询等消息(≤50 秒;超时返回空,不报错) |
|
|
106
|
+
| `lan_relay_peers` | 谁在线(120 秒内有请求即在线)+ hub 是否可达 |
|
|
107
|
+
| `lan_relay_sessions` | 列出本机活跃会话(用于回复时指定对方 `to_session`) |
|
|
108
|
+
| `lan_relay_status` | 总览:角色、hub、连通性、peer、唤醒统计;排障先调它 |
|
|
109
|
+
| `lan_relay_configure` | 用对话完成配置(等价设置页):`role=server/client/off`、`join_code`、`relay_url`、`token`、`self`、`port`、`regenerate_token` |
|
|
110
|
+
|
|
111
|
+
典型用法(Agent A 在机器 A):
|
|
112
|
+
|
|
113
|
+
> 帮我给 pc2 发消息,让它把 `logs/app.log` 最后 50 行贴回来,然后等 60 秒。
|
|
114
|
+
|
|
115
|
+
Agent A:`lan_relay_send(to="pc2", text="请把 logs/app.log 最后 50 行贴回来…")` → `lan_relay_wait(timeout_seconds=50)` → 拿到回复。
|
|
116
|
+
|
|
117
|
+
机器 B 的插件收到消息后**自动投递并唤醒**目标会话(不需要人再说话);目标会话没打开也能用 `cold_session=prompt` 冷启动。
|
|
118
|
+
|
|
119
|
+
> **成本提示**:一次投递 = 自动跑一轮模型调用。不需要时把 `push.enabled` 设为 `false`(改完保存/重启生效)。
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 6. 加入码
|
|
124
|
+
|
|
125
|
+
服务端设置页会生成一行 `dshrelay1.xxxxx` 文本,内含 **hub 地址 + token + 服务端 peer 名**(base64url,不加密)。
|
|
126
|
+
对端粘贴即可,不用手抄 IP 和 token。**重新生成 token** 会让旧加入码失效,需要把新加入码重新发给对端。
|
|
127
|
+
|
|
128
|
+
安全边界:加入码等同明文 token,只在可信局域网内传递;不要把 8787 暴露到公网,跨公网请用 Tailscale / WireGuard 等隧道。
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 7. 防火墙与网络
|
|
133
|
+
|
|
134
|
+
- hub 监听 `0.0.0.0:8787`,**只建议在可信局域网使用**。
|
|
135
|
+
- Windows 防火墙开启时,需要在服务端放行入站 TCP 8787(一次即可):
|
|
136
|
+
- 设置页 **一键放行防火墙**(弹 UAC 授权,规则限定 Private + 本地子网);
|
|
137
|
+
- 或管理员 PowerShell:
|
|
138
|
+
```powershell
|
|
139
|
+
New-NetFirewallRule -DisplayName "DSH LAN Relay 8787" -Direction Inbound -Protocol TCP -LocalPort 8787 -Action Allow -Profile Private -RemoteAddress LocalSubnet
|
|
140
|
+
```
|
|
141
|
+
- 精简版 Windows 没有 NetSecurity 模块时,脚本会自动退回 `netsh advfirewall firewall add rule ...`。
|
|
142
|
+
- 两台机器要在同一子网;跨网段需要把规则的 `LocalSubnet` 换成对方网段。
|
|
143
|
+
- 多网卡时加入码默认用第一个局域网 IPv4;如果对方连不上,在服务端设置页的「本机地址」里换一个地址,手动把地址和 token 填到对端。
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 8. 从旧版(0.4.x / `dsh-lan-relay-push` + MCP 连接器)迁移
|
|
148
|
+
|
|
149
|
+
新插件**完全替代**旧链路,配置文件沿用,不需要重新配对:
|
|
150
|
+
|
|
151
|
+
1. 安装 `dsh-lan-relay` bundle(见第 2 节)。
|
|
152
|
+
2. 在 **插件** 页把旧的 `dsh-lan-relay-push` bundle **卸载/关闭**(否则两边都会唤醒,消息会重复投递)。
|
|
153
|
+
3. **MCP 连接器**里删除 `lan-relay` 连接(旧 MCP 工具 `mcp__lan_relay__relay_*` 不再需要;插件已原生注册工具)。
|
|
154
|
+
4. 如果装过开机自启(计划任务 `DSH-LAN-Relay-Hub` / 启动文件夹快捷方式 / Run 键),删掉:
|
|
155
|
+
```powershell
|
|
156
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\install-autostart.ps1 -Remove
|
|
157
|
+
```
|
|
158
|
+
现在 hub 跟着 DSH 启动,不需要独立自启项。
|
|
159
|
+
5. 打开 **设置 → 局域网中继** 确认角色与连通性(旧配置里已有 token/地址,会自动推断成客户端;服务端机器选「服务端」保存即可)。
|
|
160
|
+
|
|
161
|
+
详细步骤见 [docs/MIGRATION-0.4-to-1.0.md](docs/MIGRATION-0.4-to-1.0.md)。
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## 9. 排障
|
|
166
|
+
|
|
167
|
+
| 现象 | 处理 |
|
|
168
|
+
|---|---|
|
|
169
|
+
| 设置页显示「未启用」 | 选「服务端」或「客户端」并保存 |
|
|
170
|
+
| 客户端「连不上 hub」 | 服务端是否在跑(同一台机器 DSH 是否开着);加入码是否含正确 IP;防火墙是否放行;用「连接测试」看具体错误 |
|
|
171
|
+
| 服务端「端口已被占用」 | 已有 hub(旧 `hub.mjs` 或另一个 DSH 实例)在 8787;停掉它,或改端口后重新生成加入码 |
|
|
172
|
+
| token 不匹配 | 两台机器 token 不一致;重新复制加入码,或在服务端「重新生成 token」后重新加入 |
|
|
173
|
+
| 消息到了但不唤醒 | 目标会话是否存在/归档;`push.wake`/`push.cold_session` 设置;`lan_relay_status` 看 `stats` 与 `last_error`;日志在 `~/.dsh/lan-relay/state/plugin.log` |
|
|
174
|
+
| 同一条消息被投两次 | 旧 `dsh-lan-relay-push` 插件还开着;或同时装了 MCP 连接器并在手动 `relay_inbox`(插件与手动工具各用独立游标) |
|
|
175
|
+
| 收不到历史消息 | 同一条消息只投一次;`lan_relay_inbox(from_seq=0, mark_read=false)` 重读 |
|
|
176
|
+
| hub 数据被删/重建 | 客户端游标可能超前,会自动归零重拉(返回 `cursor_reset: true`) |
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## 10. 开发与测试
|
|
181
|
+
|
|
182
|
+
```powershell
|
|
183
|
+
npm test # 端到端 smoke(31 项)+ 内核/插件/前端结构测试
|
|
184
|
+
npm run test:unit # 只跑 node:test 三组
|
|
185
|
+
node hub.mjs --port 8787 --token test --data-dir .\tmp-hub # 独立 CLI hub(兜底)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
| 文件 | 作用 |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `index.js` | Host 半:角色开关、内嵌 hub、工具、自动唤醒、管理 API |
|
|
191
|
+
| `client.js` | Web 半:设置 → 局域网中继 |
|
|
192
|
+
| `lib/hub-server.mjs` | 可内嵌的 hub 内核(`createHub()`,无进程副作用) |
|
|
193
|
+
| `lib/join-code.mjs` | 加入码编解码 |
|
|
194
|
+
| `lib/core.mjs` | 长轮询 / 按会话投递 / 冷启动唤醒 |
|
|
195
|
+
| `lib/relay-client.mjs` | HTTP 客户端 + 游标 |
|
|
196
|
+
| `lib/plugin-config.mjs` | 配置读写、角色推断、token 生成 |
|
|
197
|
+
| `cordis.patch.yml` | bundle patch(插入 `lan-relay` 行) |
|
|
198
|
+
| `test/*.test.mjs` | hub 内核 / 插件集成(含真实 hub + 唤醒投递)/ Web 半结构测试 |
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 11. 限制
|
|
203
|
+
|
|
204
|
+
1. hub 在 DSH 进程内:**服务端机器的 DSH 关掉后**,其他机器发不出新消息(已入队消息不丢);需要 7×24 的话让服务端 DSH 常驻。
|
|
205
|
+
2. 同一台机器只能有一个 hub 占着同一个端口;多个 DSH 实例同时以 server 角色启动会有一个报端口占用(这是预期保护)。
|
|
206
|
+
3. 明文 HTTP + 明文 token,只适合可信局域网;跨不可信网络请用隧道。
|
|
207
|
+
4. 冷启动唤醒会真的把会话 resume 起来跑一轮(消耗 token);审批策略为 `ask` 且 GUI 没打开时,需要审批的操作会 fail-closed。
|
|
208
|
+
5. 大文件不要塞消息正文(≤32000 字符);落盘后发路径,或走临时 HTTP + 校验和。
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## 附录 A:不用插件时的兜底(旧链路,保留兼容)
|
|
213
|
+
|
|
214
|
+
这些文件仍然可用,适合脚本、CI、或不能装插件的机器:
|
|
215
|
+
|
|
216
|
+
- `hub.mjs`:独立 hub 进程(`node hub.mjs --config ~/.dsh/lan-relay/config.json`)。
|
|
217
|
+
- `mcp-server.mjs`:MCP stdio server,把 5 个能力包装成 MCP 工具(需要 MCP 连接器配置)。
|
|
218
|
+
- `relay-cli.mjs`:命令行收发(`node relay-cli.mjs status|peers|send|wait`)。
|
|
219
|
+
- `scripts/setup.ps1`:写配置 + 打印 MCP 配置片段(旧流程)。
|
|
220
|
+
- `scripts/install-autostart.ps1`:给独立 hub 进程装开机自启(新插件不需要)。
|
|
221
|
+
- `examples/skill-lan-relay/SKILL.md`:没有 MCP 时让 Agent 用 CLI 的 skill。
|
|
222
|
+
|
|
223
|
+
协议与数据格式没变,新旧客户端可以混用(旧 hub 也能服务新插件,反之亦然)。
|