dsh-lan-relay 1.0.0 → 1.0.2

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.
Files changed (2) hide show
  1. package/README.md +148 -137
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,223 +1,234 @@
1
1
  # dsh-lan-relay
2
2
 
3
- > **标准 DeepSeek Harness(DSH)插件**:让**局域网内多台机器上的 DSH Agent 互相通信**。
4
- > 一个包、一次安装、一个设置页:一台机器在 DSH 进程内当 hub,其余机器粘贴**加入码**即可加入;
5
- > 消息离线补投,收到消息可**自动唤醒**目标会话。不需要单独的 hub 进程、不需要 MCP 连接器、不需要计划任务。
3
+ > **让不同机器上的 DeepSeek Harness Agent 直接对话。**
4
+ > 一个标准 DSH 插件:一台机器在 DSH 进程内当 hub,其余机器粘贴**加入码**即可加入;
5
+ > 消息离线补投、长轮询等回复、收到消息自动唤醒目标会话。
6
6
  >
7
- > **版本** v1.0.0 · **License** MIT · **Node** ≥ 18(随 DSH 运行时提供) · **DSH** ≥ 0.2.1-rc.2
7
+ > MIT · DSH ≥ 0.2.1-rc.2 · Windows / macOS / Linux
8
8
 
9
9
  ---
10
10
 
11
- ## 1. 它解决什么
11
+ ## 1. 特性
12
12
 
13
- | 场景 | 用什么 |
14
- |---|---|
15
- | 同一台机器、同一个 DSH 里的多 Agent 协作 | 内置 **Agent Teams**(`spawn_teammate` / `send_message` / 任务板),不需要本项目 |
16
- | **不同机器**上的 DSH Agent 互相发消息、等回复、跨机器唤醒 | **本项目** |
17
-
18
- 内置 Agent Teams 不跨进程/跨主机;dsh-lan-relay 补的就是这个缺口。
13
+ - **一个包、一次安装**:标准 DSH bundle(Host 半 + Web 半),在「插件 → 添加插件」里输入包名即可装好。
14
+ - **零外部依赖**:只用 Node 内置模块,不拉第三方包,不依赖 DSH 内部 API 的私有实现。
15
+ - **进程内 hub**:服务端不需要额外进程、不需要开机自启项;hub 跟着 DSH 启动和退出。
16
+ - **加入码配对**:服务端一键生成一行 `dshrelay1.…`,内含地址 + token;对端粘贴即可,不用抄 IP。
17
+ - **离线队列 + 长轮询**:消息落盘,接收方下次在线时补投;`lan_relay_wait` 最多等 50 秒。
18
+ - **自动唤醒**:消息到达后投递到指定会话并让 Agent 跑一轮;目标会话没打开也能冷启动。
19
+ - **全图形化配置**:设置 → 局域网中继:角色、端口、token、加入码、在线 peer、连接测试、防火墙放行。
20
+ - **原生 Agent 工具**:7 个 `lan_relay_*` 工具,装好即可调用,无需额外配置。
21
+ - **对话式配置**:不想点界面时,让 Agent 调 `lan_relay_configure` 就能切角色/加入。
19
22
 
20
23
  ---
21
24
 
22
- ## 2. 一键安装(推荐路径)
25
+ ## 2. 快速开始
26
+
27
+ 前置:两台机器都装了 DSH(≥ 0.2.1-rc.2),在同一局域网、能互相 ping 通。
28
+ 更详细的分步说明(含换 token / 换端口 / 换机器)见 [docs/TWO-MACHINE-SETUP.md](docs/TWO-MACHINE-SETUP.md)。
29
+
30
+ ### 第一步:两台机器都安装插件
31
+
32
+ **图形界面**:侧边栏 → **插件** → **添加插件** → 输入 `dsh-lan-relay` → 安装。
33
+
34
+ **或命令行**:
35
+
36
+ ```powershell
37
+ dsh plugin --profile desktop add dsh-lan-relay
38
+ ```
39
+
40
+ ### 第二步:服务端机器
41
+
42
+ 1. 打开 **设置 → 局域网中继**。
43
+ 2. **运行角色** 选 **服务端** → **保存**。
44
+ 3. 页面会显示:`Hub 状态:运行中`、端口 `8787`、**Token**、**加入码**(`dshrelay1.…`)、本机地址。
45
+ 4. 防火墙开着的话,点 **一键放行防火墙** → 在 UAC 里点「是」。
46
+ 5. 点加入码旁边的 **复制**,把这一行发给另一台机器。
47
+
48
+ ### 第三步:客户端机器
23
49
 
24
- 1. DSH 侧边栏 → **插件(Plugins)** → **添加插件** → 输入包名 `dsh-lan-relay`(npm 发布后),或 Git 地址 / 本地目录。
25
- 2. 打开 **设置 → 局域网中继**:
26
- - 选一台机器当服务端:**运行角色 → 服务端 → 保存**。插件会在 DSH 进程内启动 hub、自动生成 token 和**加入码**。
27
- - 其他机器:**运行角色 → 客户端**,把服务端页面上的**加入码**粘贴进来 → **保存**。
28
- 3. (仅当 Windows 防火墙开着)在服务端页面点 **一键放行防火墙**,在弹出的 UAC 里点「是」;也可以手动执行页面给出的命令。
50
+ 1. **设置 → 局域网中继** → **运行角色** 选 **客户端**。
51
+ 2. 把加入码粘贴到 **加入码** 输入框(会显示识别预览)。
52
+ 3. **保存**。顶部显示 **客户端已连接**,`在线 peer` 里出现两台机器。
29
53
 
30
- 完成后:设置页顶部显示「服务端运行中 / 客户端已连接」,`在线 peer` 里能看到对方机器。
31
- **hub 与轮询都在 DSH 进程内**,随 DSH 启动/退出,没有额外进程和自启项。
54
+ ### 第四步:验证
32
55
 
33
- > **不想点界面?** 也可以直接在会话里让 Agent 配置,例如
34
- > 「把本机设成局域网中继的服务端」「用这个加入码加入:dshrelay1.…」——
35
- > 插件提供了 `lan_relay_configure` 工具,和设置页写的是同一份配置。
36
- > (DS Bot 等自定义侧边栏模式里设置页入口可能被替换,用这个方式最省事。)
56
+ 在任意一台机器的会话里说:
37
57
 
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 后就是上面的「输入包名」一步。
58
+ > 用 lan_relay_peers 看下在线机器,然后给 pc1 发消息:"ping from pc2",并等 30 秒看回复。
59
+
60
+ 对端 Agent 会自动被唤醒并回复。
44
61
 
45
62
  ---
46
63
 
47
- ## 3. 架构(一个包,两半)
64
+ ## 3. 工作原理
48
65
 
49
66
  ```
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 ────┘
67
+ 机器 A(服务端) 机器 B(客户端)
68
+ ┌────────────────────────────────────────┐ ┌────────────────────────────────────────┐
69
+ │ DSH 进程 │ │ DSH 进程 │
70
+ │ ┌─ Host 半 ─────────────────────────┐ │ │ ┌─ Host 半 ─────────────────────────┐ │
71
+ │ │ 内嵌 hub 0.0.0.0:8787 │ │ │ │ 中继客户端(HTTP 长轮询) │ │
72
+ │ │ 中继客户端 127.0.0.1:8787 │◄─┼────┼──┤ 7 个 Agent 工具 │ │
73
+ │ │ 7 个工具 + 自动唤醒 │ │ │ │ 7 个工具 + 自动唤醒 │ │
74
+ │ └───────────────────────────────────┘ │ │ └───────────────────────────────────┘ │
75
+ │ ┌─ Web 半 ──────────────────────────┐ │ │ ┌─ Web 半 ──────────────────────────┐ │
76
+ │ │ 设置 → 局域网中继 │ │ │ │ 设置 → 局域网中继 │ │
77
+ │ └───────────────────────────────────┘ │ │ └───────────────────────────────────┘ │
78
+ └────────────────────────────────────────┘ └────────────────────────────────────────┘
79
+ └───────────── 明文 HTTP + x-relay-token(仅局域网)──────────────┘
66
80
  ```
67
81
 
68
- - **Host 半**:读 `~/.dsh/lan-relay/config.json`,按 `role` 启/停内嵌 hub、注册工具、后台长轮询并唤醒会话,并给设置页提供同源管理 API。
69
- - **Web 半**:只负责「设置 → 局域网中继」这一页,所有写入都通过 Host 半的 `/lan-relay/api/*`。
70
- - 配置文件与旧版 hub / MCP server / CLI **完全兼容**,只是多了 `role` 字段。
82
+ - **Host 半**(`index.js`):读配置 → 按角色启停内嵌 hub → 注册工具 → 后台长轮询并唤醒会话 → 给设置页提供同源管理 API。
83
+ - **Web 半**(`client.js`):只渲染设置页;所有读写都走 Host 半的 `/lan-relay/api/*`(仅回环地址可访问)。
84
+ - **配置**:`~/.dsh/lan-relay/config.json`;**消息落盘**:`~/.dsh/lan-relay/hub/messages.jsonl`(最多 5000 条 / 8MB 轮转)。
85
+ - 协议:`/api/health`、`/api/peers`、`/api/inbox`、`/api/wait`、`/api/send`,全部要 `x-relay-token`(定长比较)。
71
86
 
72
87
  ---
73
88
 
74
- ## 4. 配置(`~/.dsh/lan-relay/config.json`)
89
+ ## 4. 设置页:局域网中继
75
90
 
76
- 一般不用手改,设置页会写它;排查或脚本化时可以直接编辑(改完在设置页点一次「刷新」,或重启 DSH)。
91
+ | 区块 | 内容 |
92
+ |---|---|
93
+ | 顶部 | 运行状态徽标(服务端运行中 / 客户端已连接 / 未启用 / 异常)、刷新 |
94
+ | 运行角色 | **服务端**(本机起 hub)/ **客户端**(连别人的 hub)/ **关闭** |
95
+ | 服务端 | 端口、本机名称、Token(显示/复制/重新生成)、加入码(复制)、本机地址、Hub 状态/消息数/最新序号/数据目录、一键放行防火墙 |
96
+ | 客户端 | 加入码粘贴(自动解析)、或手填地址 + token、连接测试、在线 peer 列表、自动唤醒统计 |
97
+ | 底部 | 保存(只在点保存时写入)、每 3 秒自动刷新状态 |
77
98
 
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` 的消息 |
99
+ 所有改动都是**本地草稿**,只有点「保存」才生效;保存后 hub/轮询会按新配置立即重启,不需要重启 DSH。
94
100
 
95
101
  ---
96
102
 
97
103
  ## 5. Agent 工具
98
104
 
99
- 装好插件后,Agent 直接可用(不需要 MCP 连接器):
100
-
101
- | 工具 | 作用 |
105
+ | 工具 | 说明 |
102
106
  |---|---|
103
- | `lan_relay_send` | 给另一台机器发消息:`to`(peer 名或 `"*"`)、`text`、可选 `to_session` / `thread` |
104
- | `lan_relay_inbox` | 拉取新消息(推进游标;`from_seq=0` 重读历史) |
105
- | `lan_relay_wait` | 长轮询等消息(≤50 秒;超时返回空,不报错) |
107
+ | `lan_relay_send` | 给另一台机器发消息:`to`(peer 名或 `"*"`)、`text`、可选 `to_session`、`thread` |
108
+ | `lan_relay_inbox` | 拉取新消息(推进游标;`from_seq=0` 可重读历史) |
109
+ | `lan_relay_wait` | 长轮询等消息(≤50 秒;超时返回空数组,不报错) |
106
110
  | `lan_relay_peers` | 谁在线(120 秒内有请求即在线)+ hub 是否可达 |
107
- | `lan_relay_sessions` | 列出本机活跃会话(用于回复时指定对方 `to_session`) |
111
+ | `lan_relay_sessions` | 本机活跃会话列表(用于回复时指定对方 `to_session`) |
108
112
  | `lan_relay_status` | 总览:角色、hub、连通性、peer、唤醒统计;排障先调它 |
109
- | `lan_relay_configure` | 用对话完成配置(等价设置页):`role=server/client/off`、`join_code`、`relay_url`、`token`、`self`、`port`、`regenerate_token` |
113
+ | `lan_relay_configure` | 对话式配置:`role`、`join_code`、`relay_url`、`token`、`self`、`port`、`regenerate_token` |
110
114
 
111
- 典型用法(Agent A 在机器 A):
112
-
113
- > 帮我给 pc2 发消息,让它把 `logs/app.log` 最后 50 行贴回来,然后等 60 秒。
115
+ ---
114
116
 
115
- Agent A:`lan_relay_send(to="pc2", text="请把 logs/app.log 最后 50 行贴回来…")` → `lan_relay_wait(timeout_seconds=50)` → 拿到回复。
117
+ ## 6. 投递与自动唤醒规则
116
118
 
117
- 机器 B 的插件收到消息后**自动投递并唤醒**目标会话(不需要人再说话);目标会话没打开也能用 `cold_session=prompt` 冷启动。
119
+ 1. 消息带 `to_session` 且该会话在线 → 精确投递并唤醒。
120
+ 2. 目标会话不在线 → `push.cold_session=prompt`(默认)用 `sessionController.prompt()` 自动 resume 并投递。
121
+ 3. 没带 `to_session` → 投给 `push.default_session`,留空则投最近活跃会话。
122
+ 4. `push.wake=false` → 只注入背景,不主动跑一轮。
123
+ 5. 冷启动失败 → 记日志;只有 `push.offline_fallback=true` 才改投其它在线会话。
124
+ 6. 插件与手动 `lan_relay_inbox` / `lan_relay_wait` 使用**独立游标**,不会互相抢消息。
118
125
 
119
- > **成本提示**:一次投递 = 自动跑一轮模型调用。不需要时把 `push.enabled` 设为 `false`(改完保存/重启生效)。
126
+ > **成本提示**:一次投递 = 自动跑一轮模型调用。不需要自动唤醒时把 `push.enabled` 设为 `false`,改用工具手动拉取。
120
127
 
121
128
  ---
122
129
 
123
- ## 6. 加入码
130
+ ## 7. 加入码与安全
124
131
 
125
- 服务端设置页会生成一行 `dshrelay1.xxxxx` 文本,内含 **hub 地址 + token + 服务端 peer 名**(base64url,不加密)。
126
- 对端粘贴即可,不用手抄 IP 和 token。**重新生成 token** 会让旧加入码失效,需要把新加入码重新发给对端。
127
-
128
- 安全边界:加入码等同明文 token,只在可信局域网内传递;不要把 8787 暴露到公网,跨公网请用 Tailscale / WireGuard 等隧道。
132
+ - 加入码 = `dshrelay1.` + base64url(`{u: 地址, t: token, n: 机器名}`),**不加密**,等同明文 token。
133
+ - 服务端「重新生成 token」后旧加入码失效,需要把新加入码发给所有客户端。
134
+ - 明文 HTTP 只适合**可信局域网**;不要把 8787 暴露到公网。跨不可信网络请用 Tailscale / WireGuard 等隧道,再把地址填进加入码。
135
+ - 管理 API 只接受回环地址请求;消息正文会明文落盘,不要把密钥当消息发。
129
136
 
130
137
  ---
131
138
 
132
- ## 7. 防火墙与网络
139
+ ## 8. 防火墙与网络
133
140
 
134
- - hub 监听 `0.0.0.0:8787`,**只建议在可信局域网使用**。
135
- - Windows 防火墙开启时,需要在服务端放行入站 TCP 8787(一次即可):
136
- - 设置页 **一键放行防火墙**(弹 UAC 授权,规则限定 Private + 本地子网);
141
+ - hub 监听 `0.0.0.0:8787`,端口可在设置页修改(改完重新生成加入码)。
142
+ - Windows 防火墙开启时,服务端需要放行入站 TCP 8787(一次即可):
143
+ - 设置页 **一键放行防火墙**(UAC 授权;规则限定 Private + 本地子网);
137
144
  - 或管理员 PowerShell:
138
145
  ```powershell
139
146
  New-NetFirewallRule -DisplayName "DSH LAN Relay 8787" -Direction Inbound -Protocol TCP -LocalPort 8787 -Action Allow -Profile Private -RemoteAddress LocalSubnet
140
147
  ```
141
148
  - 精简版 Windows 没有 NetSecurity 模块时,脚本会自动退回 `netsh advfirewall firewall add rule ...`。
142
- - 两台机器要在同一子网;跨网段需要把规则的 `LocalSubnet` 换成对方网段。
143
- - 多网卡时加入码默认用第一个局域网 IPv4;如果对方连不上,在服务端设置页的「本机地址」里换一个地址,手动把地址和 token 填到对端。
149
+ - 两台机器需在同一子网;跨网段把 `LocalSubnet` 换成对方网段。
150
+ - 多网卡时加入码默认用第一个局域网 IPv4;连不上就在「本机地址」里换一个,手动填到对端。
144
151
 
145
152
  ---
146
153
 
147
- ## 8. 从旧版(0.4.x / `dsh-lan-relay-push` + MCP 连接器)迁移
148
-
149
- 新插件**完全替代**旧链路,配置文件沿用,不需要重新配对:
154
+ ## 9. 配置参考
150
155
 
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/地址,会自动推断成客户端;服务端机器选「服务端」保存即可)。
156
+ 一般不用手改(设置页会写)。排查或脚本化时可编辑 `~/.dsh/lan-relay/config.json`:
160
157
 
161
- 详细步骤见 [docs/MIGRATION-0.4-to-1.0.md](docs/MIGRATION-0.4-to-1.0.md)。
158
+ | 字段 | 默认 | 说明 |
159
+ |---|---|---|
160
+ | `role` | 自动推断 | `server` / `client` / `off` |
161
+ | `self` | 主机名 | 本机 peer 名(小写字母/数字/`._-`,≤32) |
162
+ | `relay_url` | — | 客户端要连的 hub 地址;服务端自动写成 `http://127.0.0.1:<port>` |
163
+ | `token` | 服务端生成 | 两台机器必须一致 |
164
+ | `hub.host` / `hub.port` | `0.0.0.0` / `8787` | 服务端监听地址与端口 |
165
+ | `hub.data_dir` | `~/.dsh/lan-relay/hub` | 消息落盘目录 |
166
+ | `state_dir` | `~/.dsh/lan-relay/state` | 游标与调试日志 |
167
+ | `push.enabled` | `true` | 是否后台长轮询并自动唤醒 |
168
+ | `push.wake` | `true` | `false` = 只注入背景 |
169
+ | `push.default_session` | `""` | 没指定 `to_session` 的消息投给哪个会话 |
170
+ | `push.poll_timeout_seconds` | `25` | 每轮长轮询秒数 |
171
+ | `push.cold_session` | `prompt` | 目标会话未打开时自动 resume(`drop` = 放弃) |
172
+ | `push.offline_fallback` | `false` | 冷启动失败后是否改投其它会话 |
173
+ | `push.require_session` | `false` | `true` 时拒收没有 `to_session` 的消息 |
162
174
 
163
175
  ---
164
176
 
165
- ## 9. 排障
177
+ ## 10. 故障排查
166
178
 
167
179
  | 现象 | 处理 |
168
180
  |---|---|
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`(插件与手动工具各用独立游标) |
181
+ | 设置页「未启用」 | 选「服务端」或「客户端」并保存 |
182
+ | 客户端连不上 hub | 服务端 DSH 是否在运行;加入码里的 IP 是否正确;防火墙是否放行;点「连接测试」看具体错误 |
183
+ | 服务端「端口已被占用」 | 8787 上已有 hub(同一台机器的另一个 DSH 实例)在跑;停掉它或换端口后重新生成加入码 |
184
+ | token 不匹配 | 两台机器 token 不一致;重新复制加入码,或在服务端重新生成 token |
185
+ | 消息到了不唤醒 | 目标会话是否存在/归档;检查 `push.wake`、`push.cold_session`;`lan_relay_status` 看 `stats` 与 `last_error`;日志在 `~/.dsh/lan-relay/state/plugin.log` |
175
186
  | 收不到历史消息 | 同一条消息只投一次;`lan_relay_inbox(from_seq=0, mark_read=false)` 重读 |
176
- | hub 数据被删/重建 | 客户端游标可能超前,会自动归零重拉(返回 `cursor_reset: true`) |
187
+ | hub 数据被重建 | 客户端游标可能超前,会自动归零重拉(返回 `cursor_reset: true`) |
188
+ | 界面入口找不到 | 自定义侧边栏模式(如 DS Bot)可能替换了设置入口;直接让 Agent 用 `lan_relay_configure` 配置,或在经典模式下打开设置 |
177
189
 
178
190
  ---
179
191
 
180
- ## 10. 开发与测试
192
+ ## 11. 开发
181
193
 
182
194
  ```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(兜底)
195
+ npm test # 31 项端到端 smoke + 9 项 node:test(hub 内核 / 插件集成 / Web 半结构)
196
+ npm run test:unit # 只跑 node:test
186
197
  ```
187
198
 
188
- | 文件 | 作用 |
199
+ | 路径 | 作用 |
189
200
  |---|---|
190
201
  | `index.js` | Host 半:角色开关、内嵌 hub、工具、自动唤醒、管理 API |
191
202
  | `client.js` | Web 半:设置 → 局域网中继 |
192
- | `lib/hub-server.mjs` | 可内嵌的 hub 内核(`createHub()`,无进程副作用) |
203
+ | `lib/hub-server.mjs` | 可内嵌 hub 内核(`createHub()`,无进程副作用) |
193
204
  | `lib/join-code.mjs` | 加入码编解码 |
194
- | `lib/core.mjs` | 长轮询 / 按会话投递 / 冷启动唤醒 |
205
+ | `lib/core.mjs` | 长轮询、按会话投递、冷启动唤醒 |
195
206
  | `lib/relay-client.mjs` | HTTP 客户端 + 游标 |
196
207
  | `lib/plugin-config.mjs` | 配置读写、角色推断、token 生成 |
197
208
  | `cordis.patch.yml` | bundle patch(插入 `lan-relay` 行) |
198
- | `test/*.test.mjs` | hub 内核 / 插件集成(含真实 hub + 唤醒投递)/ Web 半结构测试 |
209
+ | `locale/` · `icon.svg` | 插件卡片标题/描述与图标 |
210
+ | `test/` | 内核 / 插件集成 / Web 半结构测试 |
199
211
 
200
- ---
212
+ 发布:
201
213
 
202
- ## 11. 限制
214
+ ```powershell
215
+ npm publish --access public # package.json 的 files 白名单已包含运行所需文件
216
+ ```
203
217
 
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 + 校验和。
218
+ > 修改 `scripts/*.ps1` 时要保留 UTF-8 BOM(PowerShell 5.1 会按 ANSI 读取无 BOM 文件,中文会解析出错)。
209
219
 
210
220
  ---
211
221
 
212
- ## 附录 A:不用插件时的兜底(旧链路,保留兼容)
222
+ ## 12. 限制
213
223
 
214
- 这些文件仍然可用,适合脚本、CI、或不能装插件的机器:
224
+ 1. hub 在 DSH 进程内:服务端机器的 DSH 关闭后,其他机器发不出新消息(已入队的不丢)。需要 7×24 就让服务端 DSH 常驻。
225
+ 2. 同一台机器同一端口只能有一个 hub;多个 DSH 实例都选服务端时,后来的会报端口占用(预期保护)。
226
+ 3. 明文 HTTP + 明文 token,只适合可信局域网。
227
+ 4. 冷启动唤醒会真的 resume 会话并跑一轮(消耗 token);审批策略为 `ask` 且 GUI 没打开时,需要审批的操作会 fail-closed。
228
+ 5. 消息正文上限 32000 字符;大文件请落盘后发路径,或走临时 HTTP + 校验和。
229
+
230
+ ---
215
231
 
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。
232
+ ## License
222
233
 
223
- 协议与数据格式没变,新旧客户端可以混用(旧 hub 也能服务新插件,反之亦然)。
234
+ MIT © ready-player-zero
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-lan-relay",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "DeepSeek Harness 局域网中继插件:一台机器在 DSH 进程内做 hub,其余机器粘贴加入码即可加入;跨机器 Agent 消息互通、离线补投、自动唤醒会话,标准 DSH bundle,装完即用。",
5
5
  "type": "module",
6
6
  "main": "./index.js",