@feiyang666/dsh-mobile-remote 1.9.0 → 2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,50 @@
1
1
  # 更新日志 / Changelog
2
2
 
3
+ ## v2.0.0 (2026-11-07)
4
+
5
+ > 适配 **dsh 0.2.2-rc.1**。这一版修掉两个真实故障,并把自研移动端适配全部删除。
6
+
7
+ ### 修复 / Fixed
8
+
9
+ - **局域网能访问但面板显示「未开启」、没有二维码**:dsh 用 `--host <网卡IP>` 启动时只监听那块
10
+ 网卡(`127.0.0.1` 上没有任何监听),旧版旁挂听众去绑同一个 `<网卡IP>:<端口>` 必然
11
+ `EADDRINUSE`,于是 `running=false`。新增 `bindInfo()` 区分两种形态:
12
+ `direct`(宿主自己绑网卡)直接视为「局域网已可达」,只补其余网卡并跳过宿主已占用的地址。
13
+ - **外网域名 502 Bad Gateway**:frpc 配置里的 `localIP = "127.0.0.1"` 指向没人监听的端口。
14
+ 现在 `localIP` 跟随宿主真实监听地址;并新增**外网入口 30s HTTP 可达性探测**,
15
+ 502 / 连不上会直接在设置页标红并显示 frpc 实际转发地址(进程活着不再等于「在线」)。
16
+
17
+ ### 移除 / Removed(官方已自带移动端适配)
18
+
19
+ - 移动端 CSS 全部删除(composer 换行、选择器限宽、iOS 16px 防缩放、Tooltip 抑制、
20
+ 设置页单栏、菜单水平钳制、侧栏抽屉样式)。
21
+ - 「上传图片」按钮与图片 intake(模拟 paste/drop)删除 —— 官方 `+ → 文件` 与粘贴/拖放已覆盖。
22
+ - 自研 Toast、composer 发送状态浮层、侧栏悬浮按钮 / 覆盖式抽屉、设置弹窗结构打标。
23
+ - 保留设备心跳脚本(设置页「已连接设备」)、`crypto.randomUUID` 内网兜底(在门禁脚本内)、
24
+ 远程访问密码门禁。
25
+
26
+ ### 变更 / Changed
27
+
28
+ - `lib/lanproxy.js`:`start(hosts, port, { upstreamHost, skipHosts })`;`status()` 增加 `upstream`。
29
+ - `lib/index.js`:`/status` 增加 `direct`、`lan.upstream`、`external.localHost`、`external.probe`。
30
+ - `lib/client.js`:直连形态开关置灰 + 「局域网直连 · 由 dsh 提供」说明卡;外网卡片展示探测结果。
31
+ - `lib/external.js`:`startExternal(..., localHost)`、`autoRestoreExternal(..., localHost)`;
32
+ 导出 `finalizeFrpcConfig` 供测试。
33
+
34
+ ### 测试 / Tests
35
+
36
+ - 新增 `tests/bind-aware.test.mjs`(4 项):上游可定制、`skipHosts` 不重复绑、
37
+ 全部地址被占用时不误报失败、frpc `localIP` 跟随宿主。
38
+ - `tests/patch.test.mjs` 43 项断言仍全部通过。
39
+
40
+ ## v1.9.1 (2026-10-24)
41
+
42
+ ### 修复 / Fixed
43
+
44
+ - **1.9.0 的 npm 包里误带了一个本地备份文件** `lib/patch.js.bak-0000`(`files` 声明的是整个 `lib`
45
+ 目录)。已将该文件移出 `lib/` 并加入 `.gitignore`,发布物恢复干净(16 个文件)。
46
+ 功能与 1.9.0 完全一致,无代码变更。
47
+
3
48
  ## v1.9.0 (2026-10-24)
4
49
 
5
50
  > 适配 **dsh 0.2.1-rc.3**。这一版重做了「对局域网开放」的实现方式——**不再改 webserver 绑定**。
package/README.md CHANGED
@@ -188,8 +188,9 @@ So for users, **installing is one command** — no YAML editing, no manual file
188
188
  - **Toggle**: `POST /__dsh_remote/toggle` → writes/removes a `webserver` override block in the profile's `cordis.patch.yml` → dsh's `watchUserPatches` (Cordis HMR) hot-reloads the webserver entry to re-listen.
189
189
  - **Device count**: mobile-injected JS heartbeats every 30s; the host keeps an active-device map (90s TTL). Each heartbeat now reports full device metadata (screen / viewport / DPR / network / current page / language / platform), shown in the expandable device rows of the settings panel.
190
190
  - **QR code**: `GET /__dsh_remote/qr?url=...` returns SVG.
191
- - **Mobile polish**: `tapIndex` injects mobile CSS/JS — composer toolbar wraps on narrow screens, selects get width-capped, iOS inputs get 16px to prevent focus zoom, and an **"Upload image" button is injected next to the + in the composer toolbar** (system file picker → DSH's native paste/drop image-intake pipeline); **DSH's native rail + hamburger drawer interactions are untouched**;
192
- - **Mobile settings page** (v1.4.2+): the native settings dialog becomes a full-screen single column on phones — the nav rail turns into a horizontally scrollable tab bar and the content column fills the remaining space; persistent native tooltip bubbles (e.g. the "stop / start / close sidebar" hints that stick on touch) are suppressed. The dialog is detected structurally, **not via harness-internal hashed class names**, so the plugin keeps working after DeepSeek Harness updates without modification. **v1.4.3** fixes the single-column settings layout — the panel was still a row-flex, collapsing the content column to zero width (blank content) and blocking vertical scroll; it now forces `flex-direction: column` plus `min-height: 0` so the options area actually scrolls on phones. It also adds a **`crypto.randomUUID` fallback for insecure contexts (LAN `http://`)**: current DSH clients call `crypto.randomUUID()` on the wire, which is only defined on HTTPS or localhost, so LAN direct access failed with `crypto.randomUUID is not a function` / `settings are unavailable in this browser`; the injected head script now provides an RFC 4122 v4 shim backed by `getRandomValues`.
191
+ - **No mobile UI patches any more** (v2.0.0): `tapIndex` only injects a ~40-line device-heartbeat script (`CLIENT_JS`). dsh 0.2.2+ already ships the mobile layout (drawer sidebar below 768px, auto-collapse at 1024px, no focus stealing on mobile UA, iOS keyboard fix, PWA), so the old mobile CSS, sidebar drawer, "Upload image" button, toast and sending indicator were removed — duplicated adaptation only fights the official implementation.
192
+ - **`crypto.randomUUID` fallback for insecure contexts** (kept in `GATE_JS`): DSH clients call `crypto.randomUUID()` on the wire; it only exists on HTTPS or localhost, so LAN `http://` access used to fail with `settings are unavailable in this browser`. The injected head script provides an RFC 4122 v4 shim backed by `getRandomValues`.
193
+ - **Tunnel reachability probe** (v2.0.0): frpc being alive only means it logged into frps. Every 30s the host now issues an HTTP probe against the public URL, so a 502 (wrong local forward address/port) is surfaced in the panel together with the local address frpc actually forwards to.
193
194
 
194
195
  ---
195
196
 
package/README.zh.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  [GitHub](https://github.com/feiyang-dev/dsh-mobile-remote) · [npm](https://www.npmjs.com/package/@feiyang666/dsh-mobile-remote) · MIT License
8
8
 
9
- **由开发者制作的 DeepSeek Harness 插件** —— 在 Web UI 设置页内置「远程控制」:连接二维码、一键开关、在线设备数,让手机通过局域网访问并操控电脑上的 DeepSeek Harness,同时提供移动端界面优化。
9
+ **由开发者制作的 DeepSeek Harness 插件** —— 在 Web UI 设置页内置「远程控制」:连接二维码、一键开关、在线设备数,让手机通过局域网/外网访问并操控电脑上的 DeepSeek Harness(移动端界面由官方 dsh 自带,插件不再注入 UI 补丁)。
10
10
 
11
11
  ![License](https://img.shields.io/badge/license-MIT-blue.svg)
12
12
  ![Node](https://img.shields.io/badge/node-%3E%3D18-339933)
@@ -20,16 +20,15 @@
20
20
 
21
21
  `dsh-mobile-remote` 是 DeepSeek Harness 生态的**移动端远程控制插件**(DSH plugin,Host + Client 双面一体包)。装好后在 WebUI **设置 → 远程控制** 出现一个管理面板:
22
22
 
23
- - **移动端上传图片**(v1.5.0):composer 工具行 **+ 加号旁新增「上传图片」按钮**,手机直接选图(系统相册 / 文件选择器)即可让 DeepSeek 识图模型识别——格式 / 数量 / 大小预检查、缩略图预览、随消息上传全部复用 DSH 原生链路,桌面端不受影响;
24
- - **移动端侧栏默认收起**(v1.9.0):窄屏下把侧栏轨道压到 0,内容区吃满整屏;左上角悬浮按钮点开为**覆盖式抽屉**(不挤压中栏),点遮罩 / Esc / 选中会话自动收起;
23
+ - **不再自带移动端 UI 补丁**(v2.0.0):官方 dsh 0.2.2 起已内置移动端适配(<768px 侧栏浮层抽屉 + 遮罩、1024px 自动塌缩、移动 UA 不抢焦点、iOS 软键盘修正、PWA),插件只保留一个设备心跳脚本;旧的移动端 CSS、侧栏抽屉、「上传图片」按钮、Toast 与发送状态浮层**全部移除**,界面完全交回官方实现;
25
24
  - **连接二维码**:自动生成 `http://<局域网IP>:<端口>` 的二维码,手机相机 / 浏览器扫码即连;
26
25
  - **裸地址直达,自动登录**(v1.8.0):直接访问裸地址 `http://192.168.x.x:3080`(不带任何 token)即可自动进入——服务端自动完成新版 dsh 的浏览器会话认证(`≥0.1.2-rc.1`),无需复制带 `?token=` 的长链接;老版 dsh 自动回退,行为不变;
27
- - **开启 / 关闭开关**(v1.9.0 重做):在局域网网卡上**旁挂一个转发听众**(`<局域网IP>:<端口>` → `127.0.0.1:<端口>`),dsh 自身的监听地址与端口**完全不动**——本机窗口、桌面端、会话都不会被打断,开关**即时生效、无需重启、不写配置**;
26
+ - **开启 / 关闭开关**(v2.0.0 适配两种绑定形态):dsh 只听回环时,在局域网网卡上**旁挂一个转发听众**(`<局域网IP>:<端口>` → `127.0.0.1:<端口>`);dsh 自己就用 `--host <网卡IP>` 启动时,直接以那块网卡为上游、只补其余网卡(同地址不再重复绑,避免 `EADDRINUSE` 导致「明明能访问却显示未开启」)。dsh 的监听地址与端口**完全不动**——本机窗口、桌面端、会话都不会被打断,开关**即时生效、无需重启、不写配置**;
28
27
  - **当前连接的设备数量**:移动端心跳上报,实时统计在线设备数;
29
28
  - **远程访问密码门禁**(v1.2.0+):管理员本机设置密码,外网隧道访问进入页面需先输密码,本机/局域网不受影响;
30
29
  - **远程访问提速**(v1.2.0+):frpc 连接池调大,缓解外网访问首屏转圈慢;
31
30
  - **更丰富的数据展示**(v1.4.0):设备列表可点击展开完整上报信息(系统 / 浏览器 / 屏幕 / 视口 / DPR / 设备内存 / CPU 核数 / 电池 / 网络 / 当前页面 / 首次连接 / 心跳次数);「运行时信息」卡(运行时长 / 开机时长 / Node 版本 / PID / CPU 型号与核数 / 系统负载 / 内存使用率 / RSS / 堆内存);**「DSH 状态」卡**(dsh 版本 / 会话总数 / 工作区列表 / 已安装插件 / 模型提供方,后台缓存);「网络接口」卡(网卡名 / IP / 掩码 / MAC);外网隧道详情(域名 / 端口 / frpc 版本 / PID / 运行时长 / 脱敏绑定码 / 日志查看);
32
- - **外网隧道真实状态**(v1.4.1):不再"假在线"——面板探测 frpc 日志确认隧道真正建立,断线重连降级「连接中」,token 鉴权失败显示红色「出错」+ 精确原因(如 `token in login doesn't match`)+ 一键重试;中转端 `FRP_TOKEN` 占位符时显示黄色警告条;隧道持续心跳保活,让中转端在线状态真实可靠;
31
+ - **外网隧道真实状态**(v1.4.1+ / v2.0.0 增强):面板探测 frpc 日志确认隧道真正建立,断线重连降级「连接中」,token 鉴权失败显示红色「出错」+ 精确原因(如 `token in login doesn't match`)+ 一键重试;**v2.0.0 起每 30 秒再对外网入口做一次 HTTP 探测**——frpc 进程活着只代表连上了 frps,本机转发地址/端口不对时中转侧对外只会回 502,现在这种「假在线」会直接在面板上标红,并显示 frpc 实际使用的本地转发地址;
33
32
  - 局域网地址列表、手机访问地址、配置位置一目了然。
34
33
 
35
34
  **核心卖点:纯命令行用户无需安装桌面端。** 官方 CLI 出于安全拒绝 `--host 0.0.0.0`;而 dsh **0.2.1-rc.3 起连 patch 层也不再接受通配地址**(`host: '0.0.0.0'` 会在配置校验阶段直接让进程退出),改绑具体网卡又会让本机回环监听消失(桌面端窗口白屏)。所以 v1.9.0 改用**旁挂 LAN 听众**:dsh 保持只听回环,插件在局域网网卡上再监听一份并转发过去——手机与电脑仍共享同一个后端进程与同一份 `~/.dsh` 数据,**会话列表、历史记录、工作区、设置全部天然双向同步,无需任何数据复制**。
@@ -185,9 +184,8 @@ dsh --profile web --patch remote-control.patch.yml
185
184
  - **开关**:`POST /__dsh_remote/toggle` → 在局域网网卡上开启 / 关闭旁挂听众。请求被转发到 `127.0.0.1:<端口>`,并把 `Host` / `Origin` 改写成回环 authority(dsh 的信任围栏对回环一律放行),因此**不需要改 dsh 任何配置、也不需要重启**。
186
185
  - **设备数**:移动端注入 JS 每 30s 心跳上报,host 维护活跃设备表(90s 过期)。每次心跳会上报完整设备元数据(屏幕 / 视口 / DPR / 网络 / 当前页面 / 语言 / 平台),设置面板的设备行可展开查看。
187
186
  - **二维码**:`GET /__dsh_remote/qr?url=...` 返回 SVG。
188
- - **移动端适配**:`tapIndex` 注入移动端 CSS/JS,composer 输入栏窄屏换行、选择器限宽、iOS 输入框 16px 防缩放、**加号旁注入「上传图片」按钮**(文件选择器选图 → 复用 DSH 原生 paste/drop intake 链路);
189
- - **移动端侧栏**(v1.9.0):窄屏下侧栏轨道压到 `0px`,内容区吃满整屏;左上角悬浮按钮唤出**覆盖式抽屉**(半透明遮罩,点遮罩 / Esc / 选中会话自动收起)。仍复用原生 toggle 按钮驱动官方 store,只把「挤压中栏」改写成「浮层」,因此原生 aria / 快捷键 / 状态一致;框架节点用 `data-dsh-mobile-frame` 标记,不依赖 harness 哈希类名;
190
- - **移动端设置页适配**(v1.4.2+):原生设置弹窗在手机上自动变为全屏单栏——导航栏变顶部横向滚动标签、内容区占满剩余空间;同时抑制触屏上常驻的原生 Tooltip 气泡(如「停止 / 开始 / 关闭菜单栏」提示文字)。通过结构标记识别设置弹窗,**不依赖 harness 内部哈希类名**,harness 升级后无需修改插件即可直接适配。**v1.4.3** 修复该单栏布局——面板原本仍是横向 `flex`,内容列被压成 0 宽度(内容空白)且无法上下滚动;现强制 `flex-direction: column` + `min-height: 0`,设置选项区在手机上可正常滚动。并新增**内网(非安全上下文)`crypto.randomUUID` 兜底**:当前 DSH 客户端在连接时直接调用 `crypto.randomUUID()`,该 Web Crypto API 仅在 HTTPS / localhost 存在,内网 http 直连会报 `crypto.randomUUID is not a function` / `settings are unavailable in this browser`;插件注入的头部脚本用 `getRandomValues` 补一个 RFC 4122 v4 实现,内网访问 / 扫码连接恢复正常。
187
+ - **前端只注入心跳脚本**(v2.0.0 起):`tapIndex` 只插一个约 40 行的设备心跳脚本(`lib/index.js` 的 `CLIENT_JS`),**不再注入任何移动端 CSS / 交互补丁**——官方 dsh 0.2.2 已自带窄屏抽屉、软键盘修正等适配,重复适配只会与官方改动打架;
188
+ - **内网(非安全上下文)`crypto.randomUUID` 兜底**(保留,见 `GATE_JS`):当前 DSH 客户端连接时直接调用 `crypto.randomUUID()`,该 Web Crypto API 仅在 HTTPS / localhost 存在,内网 http 直连会报 `crypto.randomUUID is not a function` / `settings are unavailable in this browser`;门禁脚本用 `getRandomValues` 补一个 RFC 4122 v4 实现,内网访问 / 扫码连接正常。
191
189
 
192
190
  ---
193
191
 
package/RELEASE_NOTES.md CHANGED
@@ -1,43 +1,36 @@
1
- # dsh-mobile-remote v1.9.0
2
-
3
- **DeepSeek Harness 移动端远程控制插件** —— 在 Web UI 设置页内置「远程控制」:连接二维码、一键开关、在线设备数,让手机通过局域网访问并操控电脑上的 DeepSeek Harness。
4
-
5
- ## 本版更新(v1.9.0)—— 让远程控制在 dsh 0.2.1+ 上重新可用
6
-
7
- 一句话:**不再改 dsh 的监听绑定,改为旁挂一个局域网听众。** 桌面端窗口、端口、会话全都不受影响。
8
-
9
- ### 为什么之前的版本用不了了
10
-
11
- | 症状 | 根因 |
12
- | --- | --- |
13
- | 开启开关后,**电脑上的窗口直接打不开/白屏** | 旧版把 `webserver.host` 改成 `0.0.0.0`。dsh 0.2.1-rc.3 起只接受具体网卡 IP,`0.0.0.0` 会让进程启动即退出;即使是具体 IP,改绑后 `127.0.0.1` 监听消失,桌面端固定连回环 → 白屏 |
14
- | **官方桌面端**里开关点了完全没反应 | 旧版按 `DSH_PROFILE` 环境变量定位 profile,而官方桌面端**不设该变量**(只把 profile 目录作为 argv 传参)→ patch 写进了 `profiles/web`,实际运行的是 `profiles/desktop` |
15
- | 写完 patch 后 **dsh 起不来**,报 `unknown tag !<tag:yaml.org,2002:js>` | `!!js` 在该 YAML schema 里只能作用于**标量**;`trustedHosts: !!js [...]` 会被当成「流式序列 + 标量标签」 |
16
- | 端口莫名变了、二维码/链接失效 | 官方桌面端用 `--port 0` 由系统分配端口,旧 patch 里重述 `port` 会让重载后的端口漂移 |
17
-
18
- ### 新版怎么做的
19
-
20
- - **旁挂 LAN 听众(`lib/lanproxy.js`)**:在 `<局域网IP>:<当前端口>` 再监听一份,反向代理到
21
- `127.0.0.1:<当前端口>`。HTTP 与 WebSocket 都通,`X-Forwarded-For` 透传真实手机 IP,
22
- 长连接不会被 keep-alive 超时误杀。**开关即时生效,无需重启 dsh、不写任何配置文件。**
23
- - **Host / Origin 改写成回环**:dsh 的 Host/Origin 信任围栏对回环一律放行,
24
- 因此局域网访问**不再需要** `trustedHosts`,也不会再出现「页面能打开、`/api` 全 403」。
25
- - **patch 只写 `connection.trustedHosts`**(外网隧道经 frp 直连真实监听时才需要),
26
- 用 `!!js "[...ctx.webStartup.trustedHosts, '域名']"` 合并启动参数,绝不覆盖 `webserver`。
27
- - **profile 路径校正**:优先 `profileContext.patchPath` —— CLI、官方桌面端、第三方壳全部适用。
28
- - **旧配置自动迁移**:清理历史遗留的 `webserver` 覆盖与 `ctx.webRuntime.trustedHosts` 块,
29
- 迁出的域名并入受管 trustedHosts;若旧绑定正在生效,会在 HMR watcher 就绪后再改写,把监听拉回回环。
30
-
31
- ### 移动端体验
32
-
33
- - **侧栏默认收起**:窄屏下侧栏轨道压到 `0px`,内容区吃满整屏(此前固定的 56px 图标 rail 在
34
- 390px 手机上仍占 14% 宽)。
35
- - **悬浮按钮唤出抽屉**:左上角悬浮汉堡按钮 → 覆盖式抽屉(不再挤压中栏)+ 半透明遮罩;
36
- 点遮罩 / Esc / 选中会话自动收起。开合仍驱动官方 store(复用原生 toggle、aria、快捷键)。
37
- - 端口变化时局域网听众 15s 内自适应重绑;`remoteEnabled` 持久化,重启自动恢复。
38
-
39
- ### 验证
40
-
41
- - `tests/patch.test.mjs`:43 项断言全通过(含「绝不写 webserver」「`!!js` 必须加引号」「旧配置迁移」)。
42
- - 实测环境:dsh 0.2.1-rc.3 + Windows;验证了「本机端口不变 + 局域网同端口可访问 +
43
- 扫码自动登录 + `/api` 不再 403 + WebSocket 升级透传 + 开关即时生效(无需重启)」。
1
+ # dsh-mobile-remote v2.0.0
2
+
3
+ **DeepSeek Harness 远程访问插件** —— 在 Web UI 设置页内置「远程控制」:连接二维码、一键开关、在线设备数,让手机通过局域网 / 外网访问并操控电脑上的 DeepSeek Harness。移动端界面从 v2.0.0 起**完全交给官方 dsh**(0.2.2 已自带)。
4
+
5
+ ## 本版更新(v2.0.0)
6
+
7
+ 一句话:**适配「dsh 自己就绑在网卡上」的启动方式,并把外网 502 从"假在线"里揪出来;同时删掉所有自研移动端 UI 补丁。**
8
+
9
+ ### 修掉的两个真实故障
10
+
11
+ | 症状 | 根因 | 修复 |
12
+ | --- | --- | --- |
13
+ | 局域网明明能访问,插件却显示**未开启**、**不显示二维码** | dsh 用 `--host 192.168.x.x` 启动时只监听那块网卡,`127.0.0.1` 上没有任何监听。旧版旁挂听众去绑**同一个** `<网卡IP>:<端口>` → `EADDRINUSE` → `running=false` | 新增 `bindInfo()`:`direct` 形态直接认定「局域网已可达」,只补其余网卡并跳过宿主已占用的地址;二维码/地址列表把宿主绑定地址排第一 |
14
+ | 外网域名打开就是 **502 Bad Gateway**,面板却显示「在线」 | frpc 配置里的 `localIP = "127.0.0.1"` 转发到一个没人监听的端口,frps 与 nginx 侧只能回 502 | frpc 的 `localIP` 跟随宿主真实监听地址(非回环时改成网卡 IP);并新增**外网入口 30s HTTP 可达性探测**,502 直接在面板标红 |
15
+
16
+ ### 移动端适配全部移除
17
+
18
+ 官方 dsh 0.2.2 起自带移动端适配(`<768px` 侧栏浮层抽屉 + 遮罩、`1024px` 自动塌缩、移动 UA 不抢焦点、iOS 软键盘光标修正、PWA 清单),继续注入自己的 CSS 只会和官方改动互相打架:
19
+
20
+ - 删除全部移动端 CSS(composer 换行 / 选择器限宽 / 16px 防缩放 / Tooltip 抑制 / 设置页单栏 / 菜单钳制 / 抽屉样式);
21
+ - 删除「上传图片」按钮与模拟 paste/drop 的图片 intake 逻辑(官方 `+ → 文件` 与粘贴/拖放链路已有);
22
+ - 删除自研 Toast、发送状态浮层、侧栏悬浮按钮与抽屉、设置弹窗结构打标;
23
+ - 保留:设备心跳脚本(设置页「已连接设备」需要)、`crypto.randomUUID` 内网兜底(在门禁脚本里)、远程访问密码门禁。
24
+
25
+ ### 其它
26
+
27
+ - `lib/lanproxy.js`:`start(hosts, port, { upstreamHost, skipHosts })`,转发上游可定制、已占用地址自动跳过;`status()` 增加 `upstream`。
28
+ - `lib/index.js`:`/status` 新增 `direct`(宿主直连形态)与 `lan.upstream`;`toggle` 在直连形态返回 `direct: true` 并说明需要改启动参数才能关闭;`external` 新增 `localHost` / `probe`。
29
+ - `lib/client.js`:直连形态下开关置灰并显示「局域网直连 · 由 dsh 提供」说明卡;外网卡片展示入口探测结果。
30
+ - 版本号提升到 **2.0.0**(移除移动端 UI 属于行为变更)。
31
+
32
+ ### 验证
33
+
34
+ - `node --test tests/patch.test.mjs`:43 项断言通过。
35
+ - 新增 `tests/bind-aware.test.mjs`:4 项断言通过(上游可定制、`skipHosts` 不重复绑、全部被占用时不误报失败、frpc `localIP` 跟随宿主)。
36
+ - 实测环境:Windows + dsh 0.2.2(`--host 192.168.3.119 --port 3080`)。修复前:`127.0.0.1:3080` = `ECONNREFUSED`,`/status` 返回 `remoteEnabled:false`,公网域名 nginx 502;修复后 `direct` 形态下 `remoteEnabled:true`、二维码正常,frpc `localIP` 改为宿主网卡地址。
package/cordis.patch.yml CHANGED
@@ -8,7 +8,10 @@
8
8
  #
9
9
  # 插件是 host + client 双面插件:
10
10
  # - host 侧(lib/index.js,inject [webServer]):
11
- # * 通过 ctx.webServer.tapIndex 注入移动端响应式 CSS / JS;
11
+ # * 局域网:宿主只绑回环时旁挂 LAN 听众;宿主用 --host <网卡IP> 启动时直接复用它;
12
+ # * 外网:经中转服务器 + frpc 隧道,并对公网入口做 30s 可达性探测(暴露 502);
13
+ # * 通过 ctx.webServer.tapIndex 仅注入一个设备心跳脚本(不含任何移动端 UI 补丁,
14
+ # 官方 dsh 0.2.2 起自带移动端适配);
12
15
  # * 通过 ctx.webServer.register 提供 /__dsh_remote/* API
13
16
  # (status / toggle / heartbeat / qr),支持设置页远程控制开关、二维码、设备数。
14
17
  # - client 侧(lib/client.js,package.json 的 dsh.client 声明):