dsh-mobile 0.4.2 → 0.4.4

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
@@ -2,13 +2,27 @@
2
2
 
3
3
  Notable changes to DSH Mobile are recorded here. GitHub Releases remain the source for downloadable packages and complete generated commit notes.
4
4
 
5
+ ## 0.4.4 - 2026-09-20
6
+
7
+ - Keep DSH running if mDNS response callbacks, the multicast-dns emitter, or the already-bound UDP discovery socket reports a network error. LAN discovery records the degraded channel and logs the error code while the authenticated HTTP and WebSocket gateway remains available (thanks @KMGTPEZY for [#95](https://github.com/saya-ch/dsh-mobile/issues/95)).
8
+ - Accept pinned cpolar and cloudflared component downloads when a proxy omits `Content-Length`, and stop reading as soon as the response exceeds the pinned size.
9
+ - Credit community PR authors, including work adapted after a PR was closed, and every historical issue author by contribution type in [CONTRIBUTORS.md](CONTRIBUTORS.md), separately from GitHub's commit-based Contributors panel.
10
+
11
+ ## 0.4.3 - 2026-09-19
12
+
13
+ - Support Linux for the Funnel, cpolar and cloudflared remote providers, including x64 and arm64 Funnel host binaries.
14
+ - Stay compatible with DSH 0.1.6-alpha.2 (plan-review without scroll marker).
15
+ - Split oversized mobile boot batches so profiles with heavy client bundles (e.g. a 21 MB office viewer) boot on phones again: the layout batch is chunked under a 16 MiB budget, single bundles at or above the per-entry cap pass through on their own `/plugins` row, and pass-through fetches get the same bounded transient retry the merged assembly already has (thanks @abworks-dev for PR #91).
16
+ - A saved LAN interface that is not connected (e.g. after switching from Wi-Fi to Ethernet) no longer fails the whole DSH boot: mobile access logs a warning, stays dormant with its refresh poller armed, and recovers on its own when the adapter returns. Genuine config/TLS errors still fail loudly (thanks @1624318455 for PR #93).
17
+ - Correct the merged boot-batch separator accounting and mark the Linux Funnel binaries executable so the license/binary check passes in CI.
18
+
5
19
  ## 0.4.2 - 2026-09-16
6
20
 
7
- - Add an Own reverse proxy provider under Remote → Self-hosted for an existing user-managed HTTPS proxy. It provides a separate authenticated private HTTP origin (default 3444), strict private bind/source-CIDR validation, custom public HTTPS ports, local configuration and safe settings-only purge.
21
+ - Add an Own reverse proxy provider under Remote → Self-hosted for an existing user-managed HTTPS proxy. It provides a separate authenticated private HTTP origin (default 3444), strict private bind/source-CIDR validation, custom public HTTPS ports, local configuration and safe settings-only purge (thanks @xingleiwu for PR #84).
8
22
  - Distinguish backend listening from unverified public HTTPS/certificate/WebSocket reachability, with localized setup, errors and diagnostics; retain the existing LAN gateway, remote pairing and Android protocol.
9
23
  - Cover the HTTPS proxy → private HTTP origin → DSH path with real loopback pairing, authenticated HTTP and WebSocket tests, including Host/Origin/forwarded-header rejection and LAN independence.
10
- - Permanently remove revoked devices from durable storage and the desktop list, terminate their active Sessions, and compact legacy `revokedAt` rows on startup. Deleted credentials are rejected as `authentication_failed`; no revocation tombstones are retained. An offline revoked device is therefore re-paired rather than shown as revoked when it reconnects.
11
- - Load a bundled Iterator compatibility script before DSH boot on the dedicated mobile frontend, preventing `Iterator is not defined` on WebViews without Iterator helpers. The script is served locally behind the existing gateway authentication and uses feature detection to preserve or repair native helpers without weakening CSP or dropping script nonces.
24
+ - Permanently remove revoked devices from durable storage and the desktop list, terminate their active Sessions, and compact legacy `revokedAt` rows on startup. Deleted credentials are rejected as `authentication_failed`; no revocation tombstones are retained. An offline revoked device is therefore re-paired rather than shown as revoked when it reconnects (thanks @xingleiwu for PR #85).
25
+ - Load a bundled Iterator compatibility script before DSH boot on the dedicated mobile frontend, preventing `Iterator is not defined` on WebViews without Iterator helpers. The script is served locally behind the existing gateway authentication and uses feature detection to preserve or repair native helpers without weakening CSP or dropping script nonces (thanks @xingleiwu for PR #86).
12
26
  - Add a cloudflared remote provider (Windows x64) in two modes. The pinned official client is downloaded from the official release page and SHA-256 verified only after confirmation, is launched with automatic updates disabled, and does not add a system service, startup item, registry entry, or PATH entry. **Quick mode** needs no account, token, or DNS record: cloudflared allocates a temporary `*.trycloudflare.com` address, which the gateway validates before adopting it — including rejecting the reserved control-plane hosts the banner can print first, such as `api.trycloudflare.com`, which would otherwise have put Cloudflare's API in the pairing QR code. **Named mode** uses a connector token, a public hostname, and a local forward port: the hostname stays the same across restarts, the token is stored only in the DSH Mobile private directory and handed to cloudflared through `TUNNEL_TOKEN` rather than the command line, and it is never returned to any client. Because Cloudflare routes the hostname to that exact port, the port is bound as configured and a taken port is reported as a hard failure instead of silently moving; readiness comes from the connector's own `Registered tunnel connection` line, since a named tunnel prints no banner. Switching back to a quick tunnel removes the stored token.
13
27
  - Let the Android app classify `*.trycloudflare.com` as a supported remote tunnel host, so a scanned cloudflared pairing link selects remote access on its own instead of being rejected while no flow has been chosen yet. A named tunnel uses a domain the operator owns, which the app cannot classify by itself, so it is accepted only while the Remote flow is active. Both require an app build that includes this change; earlier builds still pair from the Remote access flow.
14
28
  - Keep the mobile gateway usable when its broadcast discovery socket cannot bind the UDP port: Windows keeps separate TCP and UDP port-exclusion tables, so the port the operating system handed the TCP listener can be refused for UDP, and another process may already hold it. Discovery now degrades on its own while mDNS, HTTP and WebSocket service continue, instead of failing the whole listener.
@@ -0,0 +1,53 @@
1
+ # 贡献者 / Contributors
2
+
3
+ GitHub 的 [Contributors 图表](https://github.com/saya-ch/dsh-mobile/graphs/contributors) 按进入默认分支的提交自动统计,无法手动加入仅提交 issue 或 PR 提案的成员。本页按实际参与方式感谢社区成员;仓库维护者与自动依赖更新仍可在 GitHub 历史记录中查看。
4
+
5
+ GitHub's Contributors graph counts commits on the default branch; issue reports and PR proposals cannot be manually added to it. This page credits community members by how they contributed, through 2026-09-20. The repository maintainer and automated dependency updates remain visible in GitHub's history.
6
+
7
+ ## 已合并 PR / Merged pull requests
8
+
9
+ | 社区成员 / Community member | 已合并 PR / Merged PRs |
10
+ | --- | --- |
11
+ | [@1624318455](https://github.com/1624318455) | [#93](https://github.com/saya-ch/dsh-mobile/pull/93) |
12
+ | [@abworks-dev](https://github.com/abworks-dev) | [#91](https://github.com/saya-ch/dsh-mobile/pull/91) |
13
+ | [@idoall](https://github.com/idoall) | [#61](https://github.com/saya-ch/dsh-mobile/pull/61), [#66](https://github.com/saya-ch/dsh-mobile/pull/66), [#67](https://github.com/saya-ch/dsh-mobile/pull/67), [#77](https://github.com/saya-ch/dsh-mobile/pull/77) |
14
+ | [@JackRushante](https://github.com/JackRushante) | [#16](https://github.com/saya-ch/dsh-mobile/pull/16) |
15
+ | [@longisland-icetea](https://github.com/longisland-icetea) | [#59](https://github.com/saya-ch/dsh-mobile/pull/59), [#60](https://github.com/saya-ch/dsh-mobile/pull/60), [#63](https://github.com/saya-ch/dsh-mobile/pull/63) |
16
+ | [@qzyqmzn](https://github.com/qzyqmzn) | [#38](https://github.com/saya-ch/dsh-mobile/pull/38), [#75](https://github.com/saya-ch/dsh-mobile/pull/75) |
17
+ | [@StrawberryAO](https://github.com/StrawberryAO) | [#34](https://github.com/saya-ch/dsh-mobile/pull/34), [#40](https://github.com/saya-ch/dsh-mobile/pull/40) |
18
+ | [@xingleiwu](https://github.com/xingleiwu) | [#79](https://github.com/saya-ch/dsh-mobile/pull/79), [#84](https://github.com/saya-ch/dsh-mobile/pull/84), [#85](https://github.com/saya-ch/dsh-mobile/pull/85), [#86](https://github.com/saya-ch/dsh-mobile/pull/86) |
19
+
20
+ ## 已吸收但未直接合并的 PR / Incorporated without a direct merge
21
+
22
+ [@BlueandwhiteXD](https://github.com/BlueandwhiteXD) 的 [#15](https://github.com/saya-ch/dsh-mobile/pull/15) 提出了并实现了 Android 键盘遮挡修复。由于发布分支已有重叠的状态栏改动,该方案改写后进入主线提交 [`09ef315`](https://github.com/saya-ch/dsh-mobile/commit/09ef31590219f2a436bd801214703338c215b00d),并在 [`04e6a0d`](https://github.com/saya-ch/dsh-mobile/commit/04e6a0da030353d4f0897419d0f692dc538a752d) 以 `Co-authored-by` 致谢。PR 的 Closed 状态不应掩盖这项已采用的代码贡献。
23
+
24
+ [@qzyqmzn](https://github.com/qzyqmzn) 的 [#32](https://github.com/saya-ch/dsh-mobile/pull/32) 和 [#37](https://github.com/saya-ch/dsh-mobile/pull/37) 被后续已合并的 [#38](https://github.com/saya-ch/dsh-mobile/pull/38) 取代;其正式贡献已列在上方。
25
+
26
+ [@BlueandwhiteXD](https://github.com/BlueandwhiteXD)'s [#15](https://github.com/saya-ch/dsh-mobile/pull/15) supplied the Android keyboard-overlap fix. It was adapted into [`09ef315`](https://github.com/saya-ch/dsh-mobile/commit/09ef31590219f2a436bd801214703338c215b00d) alongside overlapping status-bar work and credited with `Co-authored-by` in [`04e6a0d`](https://github.com/saya-ch/dsh-mobile/commit/04e6a0da030353d4f0897419d0f692dc538a752d). Its Closed PR status does not mean the code contribution was rejected. @qzyqmzn's [#32](https://github.com/saya-ch/dsh-mobile/pull/32) and [#37](https://github.com/saya-ch/dsh-mobile/pull/37) were superseded by merged [#38](https://github.com/saya-ch/dsh-mobile/pull/38).
27
+
28
+ ## 问题反馈与建议 / Issue reports and ideas
29
+
30
+ 以下名单包括提出问题、复现缺陷和建议功能的成员;出现在本表不表示提交过代码。 / These members opened repository issues; listing them does not imply code authorship.
31
+
32
+ | 反馈贡献者 / Issue reporter | 提交的问题 / Issues |
33
+ | --- | --- |
34
+ | [@1624318455](https://github.com/1624318455) | [#92](https://github.com/saya-ch/dsh-mobile/issues/92) |
35
+ | [@CESAEREE](https://github.com/CESAEREE) | [#1](https://github.com/saya-ch/dsh-mobile/issues/1) |
36
+ | [@CharlesLueng](https://github.com/CharlesLueng) | [#68](https://github.com/saya-ch/dsh-mobile/issues/68) |
37
+ | [@chmzs](https://github.com/chmzs) | [#73](https://github.com/saya-ch/dsh-mobile/issues/73) |
38
+ | [@idoall](https://github.com/idoall) | [#42](https://github.com/saya-ch/dsh-mobile/issues/42), [#45](https://github.com/saya-ch/dsh-mobile/issues/45), [#46](https://github.com/saya-ch/dsh-mobile/issues/46), [#47](https://github.com/saya-ch/dsh-mobile/issues/47), [#62](https://github.com/saya-ch/dsh-mobile/issues/62), [#64](https://github.com/saya-ch/dsh-mobile/issues/64) |
39
+ | [@IvyC-zz](https://github.com/IvyC-zz) | [#58](https://github.com/saya-ch/dsh-mobile/issues/58), [#78](https://github.com/saya-ch/dsh-mobile/issues/78) |
40
+ | [@jillkayat](https://github.com/jillkayat) | [#10](https://github.com/saya-ch/dsh-mobile/issues/10) |
41
+ | [@KMGTPEZY](https://github.com/KMGTPEZY) | [#95](https://github.com/saya-ch/dsh-mobile/issues/95) |
42
+ | [@LWping](https://github.com/LWping) | [#94](https://github.com/saya-ch/dsh-mobile/issues/94) |
43
+ | [@oliverwan97](https://github.com/oliverwan97) | [#26](https://github.com/saya-ch/dsh-mobile/issues/26) |
44
+ | [@rgshendong](https://github.com/rgshendong) | [#87](https://github.com/saya-ch/dsh-mobile/issues/87) |
45
+ | [@RonaldinhoL](https://github.com/RonaldinhoL) | [#89](https://github.com/saya-ch/dsh-mobile/issues/89) |
46
+ | [@shengyvself](https://github.com/shengyvself) | [#13](https://github.com/saya-ch/dsh-mobile/issues/13), [#14](https://github.com/saya-ch/dsh-mobile/issues/14) |
47
+ | [@sortjiajun](https://github.com/sortjiajun) | [#90](https://github.com/saya-ch/dsh-mobile/issues/90) |
48
+ | [@StrawberryAO](https://github.com/StrawberryAO) | [#39](https://github.com/saya-ch/dsh-mobile/issues/39) |
49
+ | [@Surpass567](https://github.com/Surpass567) | [#80](https://github.com/saya-ch/dsh-mobile/issues/80), [#81](https://github.com/saya-ch/dsh-mobile/issues/81) |
50
+ | [@taki-ohh](https://github.com/taki-ohh) | [#19](https://github.com/saya-ch/dsh-mobile/issues/19) |
51
+ | [@Xingcheng-wang](https://github.com/Xingcheng-wang) | [#76](https://github.com/saya-ch/dsh-mobile/issues/76) |
52
+ | [@Yurzi](https://github.com/Yurzi) | [#17](https://github.com/saya-ch/dsh-mobile/issues/17) |
53
+ | [@Ztyss](https://github.com/Ztyss) | [#22](https://github.com/saya-ch/dsh-mobile/issues/22), [#23](https://github.com/saya-ch/dsh-mobile/issues/23) |
package/README.en.md CHANGED
@@ -24,20 +24,21 @@
24
24
  <a href="#third-party-plugin-compatibility">Third-party plugins</a> ·
25
25
  <a href="#security">Security</a> ·
26
26
  <a href="#compatibility">Compatibility</a> ·
27
+ <a href="#contributors">Contributors</a> ·
27
28
  <a href="CHANGELOG.md">Changelog</a> ·
28
29
  <a href="README.md">简体中文</a>
29
30
  </p>
30
31
 
31
32
  > DSH Mobile is a DeepSeek Harness community plugin; the native app supports Android only.
32
33
  >
33
- > **0.4.2 update**: adds an own HTTPS reverse proxy and the cloudflared remote channel (quick and named tunnels) with on-demand component installation, plus one-command frps + Caddy deployment. The provider chooser and panel copy were re-measured at its real 380 px width, and the on-demand download no longer dies on a redirect or hides its failure message. [Details](CHANGELOG.md).
34
+ > **0.4.4 update**: runtime mDNS or UDP discovery errors no longer take down DSH, and component downloads accept proxy responses without `Content-Length`. [Details](CHANGELOG.md).
34
35
  >
35
- > **Upgrade reminder**: the 0.4.2 plugin continues to work with the 0.4.0 Android app and existing devices do not need re-pairing; a named tunnel must be scanned from inside the app's Remote flow. Install the 0.4.2 app as well if you want this Android build. [Compatibility notes](#compatibility).
36
+ > **Upgrade reminder**: the 0.4.4 plugin continues to work with existing Android apps and paired devices do not need re-pairing. Install the 0.4.4 app if you want this Android build. [Compatibility notes](#compatibility).
36
37
 
37
38
  <p align="center">
38
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.4.2/dsh-mobile-android-v0.4.2.apk"><img src="assets/brand/app-icon-rounded.svg" alt="DSH Mobile Android app icon" width="72" height="72"></a><br>
39
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.4.2/dsh-mobile-android-v0.4.2.apk"><strong>Download Android app 0.4.2</strong></a><br>
40
- <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.4.2">Release notes and checksums</a></sub>
39
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.4.4/dsh-mobile-android-v0.4.4.apk"><img src="assets/brand/app-icon-rounded.svg" alt="DSH Mobile Android app icon" width="72" height="72"></a><br>
40
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.4.4/dsh-mobile-android-v0.4.4.apk"><strong>Download Android app 0.4.4</strong></a><br>
41
+ <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.4.4">Release notes and checksums</a></sub>
41
42
  </p>
42
43
 
43
44
  DSH Mobile is a DeepSeek Harness plugin that lets a mobile browser or the Android app connect over a protected LAN or an optional Tailscale Funnel, cpolar, cloudflared, self-hosted FRP, or own reverse-proxy remote path. Local and remote access keep the same sessions, Workspaces, messages, and tools while using separate switches and paired-device stores without modifying DeepSeek Harness source.
@@ -50,13 +51,12 @@ It also lets you customize the phone from a DSH conversation: `/mobile <what you
50
51
 
51
52
  - **Continue DSH work from a phone**: the same sessions, Workspaces, messages, and tools, in real time.
52
53
  - **Customize the phone UI by talking to DSH**: change the mobile layout, interactions, and features from a conversation; open pages refresh within seconds.
53
- - **A dedicated touch layout**: session drawer, tool details, settings, question cards, and composer reorganized for phones. Native app screens follow the Android system locale in Simplified Chinese, English, or Italian. Plugin-owned Web UI follows DSH's selected locale; Italian resources are ready for a future DSH Italian locale.
54
- - **Image attachments**: file selection uses DSH's native **Add** group; DSH Mobile only adds **Take photo** to that group, and captured images follow DSH's native attachment flow.
55
- - **Auto-discovery, no re-pairing**: Wi-Fi, hotspot, or IP changes normally recover automatically.
56
- - **One-click connection diagnostics**: check versions, gateway, network interface, firewall, and the remote path; stable reason codes are localized in the UI, and the copied report excludes credentials and complete addresses.
57
- - **One-click approval for third-party plugin WebSockets**: the diagnostics view groups blocked plugin connections by directory (with attempt counts); allowing a path unblocks that exact path while everything unapproved stays blocked, and a red badge marks the sidebar entry until reviewed (#47). If a plugin keeps failing to connect (for example a terminal reporting 1006), first look at the diagnostics view for blocked connections and approve them in one click — manual configuration is usually unnecessary.
58
- - **Faster reconnection**: trusted connections race during restore, revisioned assets are reused, and mobile boot batches are compressed.
59
- - **Three pairing options**: scan a QR code, paste a pairing link, or enter a key.
54
+ - **A dedicated touch layout**: session drawer, tool details, settings, question cards, and composer reorganized for phones; the app follows the system locale (Chinese/English/Italian), plugin UI follows DSH's locale.
55
+ - **Every remote path covered**: Tailscale, cpolar, cloudflared quick/named tunnels, self-hosted FRP, or your own reverse proxy.
56
+ - **Pairing and multi-device**: pair once via QR code, link, or key; Wi-Fi, hotspot, or IP changes normally recover automatically; the app shows all paired computers together in one device list (LAN and every remote), each with live reachability — switch, re-pair, or delete in one tap.
57
+ - **One-click diagnostics and approval**: check versions, gateway, network interface, firewall, and the remote path with a redacted report; approve blocked third-party plugin connections per exact path.
58
+ - **Task system notifications**: completion and pending-input alerts via Android system notifications, enabled from the app foreground menu, with redacted lock-screen text.
59
+ - **Defense in depth**: dedicated HTTPS with pinned certificates, Keystore-backed credentials, device tokens sent only to their exact Origin, third-party WebSockets blocked by default.
60
60
 
61
61
  A paired device is fully trusted and can operate the DSH on the computer. Use this only on a trusted home or office LAN, or a trusted VPN.
62
62
 
@@ -133,7 +133,8 @@ Remote providers may impose bandwidth and connection limits: the [cpolar Free pl
133
133
  - **cpolar**: select **Install official component**, sign in to the cpolar dashboard and obtain an Authtoken, paste it, then select **Save and connect**. The component is downloaded into the plugin's private directory only after confirmation; free temporary addresses may change after DSH or cpolar restarts.
134
134
  - **Self-hosted FRP (advanced)**: expand **Self-hosted connection**, enter the VPS, frps port, shared token, and public HTTPS origin. The origin may use your domain or the VPS public IPv4 address (for example, `https://203.0.113.10` — substitute your own real address; documentation ranges are rejected). Apply the restricted template manually or enter an SSH user, port, and local private-key path for automatic deployment. Automatic deployment supports Ubuntu/Debian with systemd, uses OpenSSH keys or an agent, refuses password auth, and does not overwrite Caddy configuration it does not manage; both deployment and server cleanup display the SSH host keys for verification against the VPS console before continuing. IPv4 mode obtains a roughly six-day Let's Encrypt IP certificate and installs daily automatic renewal. Install the official `frpc` on demand and verify the path afterward. A reviewable uninstall script or one-click server cleanup removes only DSH Mobile-owned services and configs. This requires Android app 0.3.3 or later. See the [English self-hosted FRP guide](docs/SELF_HOSTED_FRP.en.md) for the complete procedure.
135
135
  - **Own reverse proxy**: open **Self-hosted connection → Own reverse proxy**, enter the public HTTPS origin (custom ports supported), private listen IPv4, separate HTTP backend port (default 3444), and allowed proxy source CIDRs, then select **Save and start backend**. This uses your existing Lucky/Nginx/Caddy without a tunnel component and requires Android app 0.4.0 or later. See the [own reverse proxy guide](docs/SELF_HOSTED_ORIGIN.en.md).
136
- - **cloudflared**: select **Install official component**. After you confirm, the plugin downloads a pinned build from the official release page into its private directory and requests a temporary public address (a quick tunnel) with **no sign-up or sign-in**. Choose this when you would rather not create an account. The quick-tunnel hostname changes on every reconnect, and Cloudflare positions quick tunnels for testing: they are rate-limited and carry no uptime guarantee, so do not rely on one for production access that must stay reachable. With a Cloudflare account and domain, switch **Tunnel type** to **Named**, then supply a connector token, a public hostname and a local forward port to get an address that survives restarts. The token is stored only in the private directory and reaches cloudflared through the environment rather than the command line; see [Cloudflare named tunnel](docs/CLOUDFLARE_TUNNEL.en.md).
136
+ - **cloudflared quick tunnel**: select **Install official component**. After you confirm, the plugin downloads a pinned build from the official release page into its private directory and requests a temporary public address (a quick tunnel) with **no sign-up or sign-in**. Choose this when you would rather not create an account. The quick-tunnel hostname changes on every reconnect, and Cloudflare positions quick tunnels for testing: they are rate-limited and carry no uptime guarantee, so do not rely on one for production access that must stay reachable; it suits temporary or verification use.
137
+ - **cloudflared named tunnel**: with a Cloudflare account and domain, switch **Tunnel type** to **Named**, then supply a connector token, a public hostname and a local forward port to get an address that survives restarts. The token is stored only in the private directory and reaches cloudflared through the environment rather than the command line; see [Cloudflare named tunnel](docs/CLOUDFLARE_TUNNEL.en.md).
137
138
  2. When the panel reports that remote access is ready, select **Create remote pairing QR code**. Own reverse proxy reports only **Backend listening**: public HTTPS, its certificate and WebSocket still require verification from your phone.
138
139
  3. In the Android app, open **Remote access** and scan the QR code to create its separate pairing.
139
140
  4. The app saves the current address and device credential for automatic reconnection. If a free cpolar address changes, scan the computer's current remote QR code to verify the connection again; clearing app data is unnecessary. A stored device token is sent only to its exact saved Origin, never to a new QR-code domain.
@@ -146,7 +147,7 @@ Self-hosted FRP generates only one HTTP vhost to the DSH loopback gateway. It ex
146
147
 
147
148
  The own-proxy HTTP backend must remain on a trusted private network: **never port-forward it publicly or bypass it by proxying to DSH or the existing LAN 3443 gateway**. CIDRs match the proxy's direct TCP peer, not forwarded headers. Preserve the external Host (including port), Origin, cookies and WebSocket. Clearing proxy settings keeps paired remote devices.
148
149
 
149
- The public remote origin still requires DSH device pairing. The bundled Funnel and the managed cpolar and cloudflared components currently support Windows x64; on-demand FRP 0.70.1 supports Windows, Linux, and macOS on x64 and arm64.
150
+ The public remote origin still requires DSH device pairing. The bundled Funnel and the managed cpolar and cloudflared components support Windows x64 and Linux x64/arm64; on-demand FRP 0.70.1 supports Windows, Linux, and macOS on x64 and arm64. See [Compatibility](#compatibility) for the per-channel OS matrix.
150
151
 
151
152
  ## Extend and customize
152
153
 
@@ -181,9 +182,9 @@ The examples above, applied:
181
182
  <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/cyberpunk-monitor-1.png" width="22%" style="margin-left:8px" alt="Mobile UI customized into a cyberpunk computer monitor">
182
183
  </p>
183
184
 
184
- ### Device management
185
+ ## Device management
185
186
 
186
- The Android app keeps LAN, cpolar, cloudflared, Tailscale Funnel, and self-hosted FRP pairings in one **Paired computers** list. The first upgrade migrates the legacy LAN and remote credentials without requiring another pairing; when an address changes, the app merges the row by the DSH installation's stable `instanceId` and keeps its custom name. Device tokens and LAN CAs remain encrypted by Android Keystore and never appear in the list or QR code.
187
+ The Android app shows multiple computers at once in one **Paired computers** list: LAN, cpolar, cloudflared, Tailscale Funnel, and self-hosted FRP pairings together. The first upgrade migrates the legacy LAN and remote credentials without requiring another pairing; when an address changes, the app merges the row by the DSH installation's stable `instanceId` and keeps its custom name. Device tokens and LAN CAs remain encrypted by Android Keystore and never appear in the list or QR code.
187
188
 
188
189
  Each row shows its custom name, transport, Origin, live reachability, and last connection time. A green dot means **Reachable**; a gray dot means **Checking**, **Temporarily unreachable**, **Pairing expired**, or **Removed on computer**. The check validates the DSH Gateway over HTTPS instead of using ICMP, so a temporary network outage is not mistaken for computer-side revocation.
189
190
 
@@ -207,7 +208,7 @@ Revoking a device permanently deletes its durable record and token digest instea
207
208
  </tr>
208
209
  </table>
209
210
 
210
- ### Third-party plugin compatibility
211
+ ## Third-party plugin compatibility
211
212
 
212
213
  The mobile adaptation keeps DSH's existing Workspace, task-management, terminal, and file-panel entry points instead of isolating third-party plugin content in a separate page. The wide-layout screenshot below shows the Android app in a wide viewport. The app adapts to the available width: phones use drawers and overlays, while wide screens use side-by-side panels; both layouts expose the same features and connection methods. DSH still loads third-party plugins itself—the mobile layer only adapts layout and access, without modifying DeepSeek Harness source.
213
214
 
@@ -215,7 +216,7 @@ Compatibility and WebSocket rules:
215
216
 
216
217
  Proxied pages allow HTTP frames for compatibility with some community plugins; those pages are unencrypted and can be altered, and browsers may still block them as mixed content. Use HTTPS for sensitive work. The same warning appears at the top of the remote panel when it is opened over HTTPS.
217
218
 
218
- - The released 0.4.0 is contract-checked against DSH `0.1.5-rc.2` (renderer-v2) and retains the `0.1.5-rc.1` LAN verification. The DSH page must expose the standard session, `main`/`panelInfo`, and `rightbar` slots; the community plugin must register its panel or sidebar content through DSH's standard entry points.
219
+ - Version 0.4.4 is contract-checked against DSH `0.1.6-alpha.2` (renderer-v2). The DSH page must expose the standard session, `main`/`panelInfo`, and `rightbar` slots; the community plugin must register its panel or sidebar content through DSH's standard entry points.
219
220
  - The gateway allows first-party DSH WebSocket paths by default, including `/sidebar/ws/terminal`. Other paths used by community sidebar plugins are blocked by default and appear in Diagnostics; the `/sidebar/ws/agent-opens` and `/sidebar/ws/agent-terminals` paths in the image are examples that must be reviewed for the actual plugin.
220
221
  - In **Connection diagnostics → Third-party WebSocket paths**, select **Allow** only for an exact path you have verified. Query strings and fuzzy prefixes are rejected; **Allow all** is not recommended. Approved paths can be removed at any time, and the same policy applies to LAN and remote connections.
221
222
  - Approval only lets that path pass through the authenticated, same-origin DSH Mobile gateway. It does not open arbitrary TCP/UDP ports or bypass device pairing. If a community plugin still fails, check the path recorded by Diagnostics and approve one path at a time.
@@ -266,19 +267,44 @@ Three layers: the Host face for discovery, pairing, HTTPS, loopback proxying, an
266
267
  - Use the LAN listener only on a trusted home, office, or hotspot network; do not add your own port forwarding.
267
268
  - A remote origin is publicly reachable, but unpaired requests cannot enter DSH; turn the remote switch off when it is not needed.
268
269
  - cpolar downloads a pinned official build only after confirmation and verifies its size and SHA-256. It installs no system service, PATH entry, or startup task, and plugin cleanup removes its managed files.
269
- - cloudflared likewise downloads a pinned build from the official GitHub Release only after confirmation and verifies the exact size and SHA-256, and it launches the client with automatic updates disabled so the running binary is always the verified one. It needs no account, token, or DNS record, stores no credential, and cleanup deletes every file it manages.
270
+ - cloudflared likewise downloads a pinned build from the official GitHub Release only after confirmation and verifies the exact size and SHA-256, and it launches the client with automatic updates disabled so the running binary is always the verified one. A quick tunnel needs no account, token, or DNS record; a named tunnel token is stored only in the plugin private directory and reaches cloudflared through the environment, and cleanup deletes every file it manages.
270
271
  - Self-hosted FRP downloads pinned official `frpc` only after confirmation and verifies the origin, exact size, SHA-256, archive paths, and executable version. The shared token never appears in status, diagnostics, or logs. Copying the server template places it on the system clipboard, so clear the clipboard after use; local cleanup removes only plugin-managed files, while the VPS is cleaned separately with the uninstall script or one-click server cleanup. Automatic deployment and server cleanup both display the SSH host keys, which must be verified against the VPS console before continuing.
271
272
  - A paired device is a fully trusted DeepSeek Harness operator and can run tools on the computer; revoke lost devices from the computer.
272
273
  - The LAN gateway listens only while Mobile Access is enabled; with it off, DSH keeps running normally on the computer.
273
274
 
274
275
  See [SECURITY.md](SECURITY.md).
275
276
 
277
+ ## Troubleshooting
278
+
279
+ - **Boot fails with `saved LAN interface "XXX" is not connected`**: the
280
+ computer switched networks (Wi-Fi/Ethernet/dock) and the previously saved
281
+ adapter is down. Either reconnect that network, re-run setup on the new
282
+ one, or set `mobile-access` to `disabled: true` in `cordis.patch.yml` if
283
+ phone access is not needed. Recent versions no longer block boot in this
284
+ case — the plugin logs a warning, stays dormant, and recovers when the
285
+ adapter returns.
286
+
276
287
  ## Compatibility
277
288
 
278
289
  The table below lists, for each plugin version, the DeepSeek Harness version it is verified to support (earlier 0.1.x releases are compatible as well). Starting with 0.3.6 the plugin no longer rejects a DSH version by number alone; newer unlisted versions are covered by CI's contract checks. History lives in [CHANGELOG.md](CHANGELOG.md).
279
290
 
291
+ ### OS support matrix
292
+
293
+ | Channel | Windows x64 | Linux x64 | Linux arm64 | macOS |
294
+ | --- | --- | --- | --- | --- |
295
+ | Local network | Yes (firewall automated) | Yes (open the firewall yourself) | Yes | Yes |
296
+ | Tailscale Funnel | Yes (bundled) | Yes (bundled) | Yes (bundled) | No |
297
+ | cpolar | Yes (on-demand) | Yes (on-demand) | Yes (on-demand) | No |
298
+ | cloudflared quick/named tunnel | Yes (on-demand) | Yes (on-demand) | Yes (on-demand) | No |
299
+ | Self-hosted FRP | Yes (on-demand) | Yes (on-demand) | Yes (on-demand) | Yes (on-demand) |
300
+ | Own reverse proxy | Yes (config only) | Yes (config only) | Yes (config only) | Yes (config only) |
301
+
302
+ On macOS, local network, self-hosted FRP, and the own reverse proxy work; the three managed components have no macOS build yet. The diagnostics firewall check currently covers Windows only and reports “not applicable” elsewhere.
303
+
280
304
  | DSH Mobile plugin | Verified DeepSeek Harness version |
281
305
  | --- | --- |
306
+ | `0.4.4` | `0.1.6-alpha.2` (local source and renderer-v2 contract check) |
307
+ | `0.4.3` | `0.1.6-alpha.2` (local source and renderer-v2 contract check) |
282
308
  | `0.4.2` | `0.1.6-alpha.1` (local source and renderer-v2 contract check) |
283
309
  | `0.4.1` | `0.1.6-alpha.1` (local source and renderer-v2 contract check) |
284
310
  | `0.3.15`, `0.3.16`, `0.4.0` | `0.1.5-rc.2` (contract check); `0.1.5-rc.1` (@idoall LAN verification) |
@@ -289,7 +315,7 @@ The table below lists, for each plugin version, the DeepSeek Harness version it
289
315
  | `0.3.0`-`0.3.3` | `0.1.2-alpha.1` |
290
316
  | `0.1.4`, `0.2.x` | `0.1.1-rc.2` |
291
317
 
292
- Existing 0.3.3–0.4.0 apps do not need re-pairing. cpolar users should use app 0.3.15 or later because earlier apps may time out before a slow first load over the free route finishes; earlier apps also use a different status-bar strategy. The 0.4.0 app adds the multi-device list, startup behavior, and computer-side revocation status; older apps continue to connect to their saved single device. App 0.1.3 or earlier requires reinstalling and pairing again.
318
+ Existing apps (0.3.3 and later) do not need re-pairing. cpolar users should use app 0.3.15 or later because earlier apps may time out before a slow first load over the free route finishes; earlier apps also use a different status-bar strategy. The 0.4.0 app adds the multi-device list, startup behavior, and computer-side revocation status; older apps continue to connect to their saved single device. App 0.1.3 or earlier requires reinstalling and pairing again.
293
319
 
294
320
  ## Uninstall
295
321
 
@@ -306,6 +332,10 @@ dsh plugin --profile web remove dsh-mobile
306
332
 
307
333
  Source users replace `dsh` with `pnpm dsh`.
308
334
 
335
+ ## Contributors
336
+
337
+ Thanks to everyone who submitted PRs, reproduced issues, or proposed improvements. [The contributors list](CONTRIBUTORS.md) credits merged PRs, PR work later incorporated without a direct merge, and issue reports separately. GitHub's sidebar Contributors panel is generated from commits on the default branch and cannot be manually extended with issue-only contributors.
338
+
309
339
  ## Development
310
340
 
311
341
  ```powershell
package/README.md CHANGED
@@ -24,20 +24,21 @@
24
24
  <a href="#第三方插件适配">第三方插件适配</a> ·
25
25
  <a href="#安全">安全</a> ·
26
26
  <a href="#兼容性">兼容性</a> ·
27
+ <a href="#贡献者">贡献者</a> ·
27
28
  <a href="CHANGELOG.md">更新记录</a> ·
28
29
  <a href="README.en.md">English</a>
29
30
  </p>
30
31
 
31
32
  > DSH Mobile 是 DeepSeek Harness 社区插件,原生 App 仅支持 Android。
32
33
  >
33
- > **0.4.2 更新**:新增自有 HTTPS 反向代理与 cloudflared 远程通道(快速隧道 + 命名隧道),cloudflared 组件改为按需安装;新增一键部署 frps + Caddy。远程提供方选择器与面板文字在真实 380px 宽度下重新校对,并修好了组件下载被重定向卡死、失败提示被刷新覆盖等问题。[详细记录](CHANGELOG.md)。
34
+ > **0.4.4 更新**:局域网发现遇到运行期 mDNS/UDP 错误时不再带崩 DSH;组件下载也能处理缺少 `Content-Length` 的代理响应。[详细记录](CHANGELOG.md)。
34
35
  >
35
- > **升级提醒**:0.4.2 插件可继续使用 0.4.0 Android App,已有设备无需重新配对;命名隧道要求 App 侧处于「远程」流程内扫码。若要使用本次 Android 构建,请同时安装 0.4.2 App。[兼容说明](#兼容性)。
36
+ > **升级提醒**:0.4.4 插件可继续使用现有 Android App,已有设备无需重新配对。若要使用本次 Android 构建,请安装 0.4.4 App。[兼容说明](#兼容性)。
36
37
 
37
38
  <p align="center">
38
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.4.2/dsh-mobile-android-v0.4.2.apk"><img src="assets/brand/app-icon-rounded.svg" alt="DSH Mobile 安卓应用图标" width="72" height="72"></a><br>
39
- <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.4.2/dsh-mobile-android-v0.4.2.apk"><strong>下载 Android App 0.4.2</strong></a><br>
40
- <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.4.2">版本说明与校验文件</a></sub>
39
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.4.4/dsh-mobile-android-v0.4.4.apk"><img src="assets/brand/app-icon-rounded.svg" alt="DSH Mobile 安卓应用图标" width="72" height="72"></a><br>
40
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.4.4/dsh-mobile-android-v0.4.4.apk"><strong>下载 Android App 0.4.4</strong></a><br>
41
+ <sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.4.4">版本说明与校验文件</a></sub>
41
42
  </p>
42
43
 
43
44
  DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App 通过局域网,或可选的 Tailscale Funnel、cpolar、cloudflared、自建 FRP 或自有反向代理远程通道连接电脑,继续使用同一份会话、工作区、消息和工具。局域网与远程访问分别启停、分别管理设备,且都不修改 DeepSeek Harness 源码。
@@ -50,13 +51,12 @@ DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App
50
51
 
51
52
  - **在手机上继续电脑端的工作**:同一份会话、工作区、消息和工具,实时同步。
52
53
  - **用对话定制手机端**:直接在 DSH 对话里改手机页面的布局、交互和功能,几秒内刷新。
53
- - **专属触屏布局**:会话抽屉、工具详情、设置、提问卡片和输入栏都按手机重新组织。App 原生页面跟随系统显示简体中文、英文或意大利文;插件界面跟随 DSH 的语言设置,意大利语资源已为 DSH 后续支持预留。
54
- - **图片附件**:文件选择使用 DSH 原生“添加”组;DSH Mobile 只在该组补充“拍照”,拍摄结果按 DSH 原生附件流程发送。
55
- - **自动发现、无需重新配对**:切换 Wi-Fi、热点或 IP 后通常自动恢复。
56
- - **一键连接诊断**:检查版本、网关、网卡、防火墙和远程通道;稳定的原因码在界面中本地化,并生成不含凭据与完整地址的脱敏报告。
57
- - **第三方插件 WebSocket 一键放行**:诊断页按目录分组记录被拦截的插件连接(含次数),点允许即放行确切路径,未批准的一律拦截;有新拦截时侧栏红点提醒(#47)。若某插件的连接一直失败(如终端报 1006),先到诊断页看看有没有被拦的连接,一键放行即可,通常无需手动配置。
58
- - **更快恢复连接**:远程重开会并行恢复可信连接、复用版本化资源,并压缩移动端启动批次。
59
- - **三种配对方式**:扫码、配对链接、密钥。
54
+ - **专属触屏布局**:会话抽屉、工具详情、设置、提问卡片和输入栏都按手机重新组织;App 跟随系统语言(简/英/意),插件界面跟随 DSH 语言。
55
+ - **多种远程通道**:Tailscale、cpolar、cloudflared 快速/命名隧道、自建 FRP、自有反向代理,按网络任选。
56
+ - **配对与多设备**:扫码、链接或密钥配对一次;切换 Wi-Fi、热点或 IP 后通常自动恢复;App 在一个设备列表中同时显示多台已配对电脑(局域网与全部远程),每台实时显示可达状态,一键切换、重新配对或删除。
57
+ - **一键诊断与放行**:检查版本、网关、网卡、防火墙和远程通道,生成脱敏报告;被拦截的第三方插件连接按确切路径一键放行。
58
+ - **任务系统通知**:任务完成与待输入以 Android 系统通知推送,在 App 前台菜单开启,锁屏文本脱敏。
59
+ - **纵深安全**:独立 HTTPS 与证书固定,凭据存 Keystore,设备令牌只发往精确 Origin,第三方 WS 默认拦截。
60
60
 
61
61
  配对设备被视为完全信任,可以操作电脑上的 DSH;建议只在可信的家庭、办公局域网或可信 VPN 中使用。
62
62
 
@@ -133,7 +133,8 @@ dsh plugin --profile web add dshmarket
133
133
  - **cpolar**:点击 **安装官方组件**,登录 cpolar 控制台取得 Authtoken,粘贴后点击 **保存并连接**。组件只会在确认后下载到插件私有目录;免费临时地址可能在 DSH 或 cpolar 重启后变化。
134
134
  - **自建 FRP(高级)**:展开 **自建连接**,填写 VPS、frps 端口、共享 Token 和公开 HTTPS 地址;公开地址可以是自己的域名,也可以直接是 VPS 公网 IPv4(例如 `https://203.0.113.10`,请换成你自己的真实地址,文档示例网段会被拒绝)。可以复制受限模板手动部署,也可以填写 SSH 用户、SSH 端口和本机私钥路径,点击 **部署 frps + Caddy** 自动部署。自动部署支持 Ubuntu/Debian + systemd,使用 OpenSSH 密钥或 ssh-agent,不接受密码,也不会覆盖非 DSH Mobile 管理的 Caddyfile;部署与清理前都会展示服务器主机指纹,需到 VPS 控制台核对后才能继续。公网 IP 模式会申请约 6 天有效的 Let’s Encrypt IP 证书并配置每日自动续期。部署完成后再安装官方 `frpc` 并验证连接。不再需要服务器时可用“复制 VPS 卸载脚本”或一键清理,只删除 DSH Mobile 自己的服务与配置。需要 Android App 0.3.3 或更高版本。详见 [自建 FRP 使用指南](docs/SELF_HOSTED_FRP.md)。
135
135
  - **自有反向代理**:展开 **自建连接 → 自有反向代理**,填写公网 HTTPS 地址(支持自定义端口)、私有监听 IPv4、独立 HTTP 后端端口(默认 3444)和代理来源 CIDR,再点击 **保存并启动后端**。适合已有 Lucky/Nginx/Caddy 的用户,无需隧道组件;需要 Android App 0.4.0 或更高版本。详见 [自有反向代理指南](docs/SELF_HOSTED_ORIGIN.md)。
136
- - **cloudflared**:点击 **安装官方组件**,插件在确认后从官方发布页下载固定版本到插件私有目录,随后自动申请一个临时公网地址(quick tunnel),**无需注册或登录**。适合不想注册账号的用户;quick tunnel 地址每次重连都会变化,官方定位为测试用途、有限流且无可用性保证,请勿用于必须长期可达的生产访问。已有 Cloudflare 账号和域名时,可把隧道类型切到 **命名隧道**,填入连接器令牌、公网域名与本机转发端口,即可获得重启后不变的固定地址(令牌只存私有目录、只经环境变量传给 cloudflared)。步骤见 [Cloudflare 命名隧道](docs/CLOUDFLARE_TUNNEL.md)。
136
+ - **cloudflared 快速隧道**:点击 **安装官方组件**,插件在确认后从官方发布页下载固定版本到插件私有目录,随后自动申请一个临时公网地址(quick tunnel),**无需注册或登录**。适合不想注册账号的用户;quick tunnel 地址每次重连都会变化,官方定位为测试用途、有限流且无可用性保证,请勿用于必须长期可达的生产访问,只适合临时或验证场景。
137
+ - **cloudflared 命名隧道**:已有 Cloudflare 账号和域名时,把隧道类型切到 **命名隧道**,填入连接器令牌、公网域名与本机转发端口,即可获得重启后不变的固定地址(令牌只存私有目录、只经环境变量传给 cloudflared)。步骤见 [Cloudflare 命名隧道](docs/CLOUDFLARE_TUNNEL.md)。
137
138
  2. 状态变为“远程访问已就绪”后,点击 **生成远程配对二维码**。自有反向代理仅显示“后端已监听”:它不验证公网连通性,仍需检查代理 HTTPS、证书与 WebSocket 并用手机验收。
138
139
  3. 在 Android App 中进入 **远程访问**,扫描二维码完成独立配对。
139
140
  4. 此后 App 会保存当前地址和设备凭据并自动重连。若 cpolar 免费临时地址发生变化,请扫描电脑端当前远程二维码重新验证连接;无需清除 App 数据。旧设备 token 只会发送到原先保存的精确 Origin,不会发送给二维码中的新域名。
@@ -146,7 +147,7 @@ Tailscale Funnel 覆盖范围广,但在中国大陆网络下可能不稳定。
146
147
 
147
148
  自有反向代理的 HTTP 后端只允许留在可信私网;**不要把它映射到公网,也不要绕过它直连 DSH 或现有 LAN 3443**。来源 CIDR 匹配代理的直接 TCP 来源,不信任转发头;反代须保留外部 Host(含端口)、Origin、Cookie 和 WebSocket。清除代理配置不会删除已配对远程设备。
148
149
 
149
- 远程公开地址仍受 DSH 设备配对保护。内置 Funnel 与托管 cpolar、cloudflared 当前支持 Windows x64;按需安装的 FRP 0.70.1 支持 Windows、Linux、macOS 的 x64 与 arm64。
150
+ 远程公开地址仍受 DSH 设备配对保护。内置 Funnel 与托管 cpolar、cloudflared 支持 Windows x64 与 Linux x64/arm64;按需安装的 FRP 0.70.1 支持 Windows、Linux、macOS 的 x64 与 arm64。各通道的系统支持矩阵见[兼容性](#兼容性)。
150
151
 
151
152
  ## 扩展与自定义
152
153
 
@@ -181,9 +182,9 @@ Tailscale Funnel 覆盖范围广,但在中国大陆网络下可能不稳定。
181
182
  <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/cyberpunk-monitor-1.png" width="22%" style="margin-left:8px" alt="/mobile 定制为赛博朋克监控面板">
182
183
  </p>
183
184
 
184
- ### 设备管理
185
+ ## 设备管理
185
186
 
186
- Android App 将局域网、cpolar、cloudflared、Tailscale Funnel 和自建 FRP 统一整理到“已配对设备”列表。首次升级会自动迁移旧版局域网与远程凭据,不要求重新配对;地址变化时按 DSH 安装的稳定 `instanceId` 合并原记录,保留自定义名称。设备 Token 和局域网 CA 继续由 Android Keystore 加密保存,不会显示在列表或二维码中。
187
+ Android App 用一个“已配对设备”列表同时显示多台电脑:局域网、cpolar、cloudflared、Tailscale Funnel 和自建 FRP 配对共处一处。首次升级会自动迁移旧版局域网与远程凭据,不要求重新配对;地址变化时按 DSH 安装的稳定 `instanceId` 合并原记录,保留自定义名称。设备 Token 和局域网 CA 继续由 Android Keystore 加密保存,不会显示在列表或二维码中。
187
188
 
188
189
  每条记录显示自定义名称、连接方式、Origin、实时可达状态和最近连接时间。绿色状态点表示“可达”,灰色状态点表示“检测中”“暂不可达”“配对已过期”或“电脑端已移除”;可达性检查直接验证 DSH Gateway,不依赖 ICMP,也不会把暂时断网误判成电脑端撤销。
189
190
 
@@ -207,7 +208,7 @@ Android App 将局域网、cpolar、cloudflared、Tailscale Funnel 和自建 FRP
207
208
  </tr>
208
209
  </table>
209
210
 
210
- ### 第三方插件适配
211
+ ## 第三方插件适配
211
212
 
212
213
  移动适配保持 DSH 原有的工作区、任务管理、终端和文件面板入口,不会把第三方插件内容隔离成另一套页面。下面的宽屏截图展示 Android App 在宽屏下的布局。App 会根据屏幕宽度自适应:手机使用抽屉和浮层,宽屏使用并排面板;两种布局共享相同的功能和连接方式。第三方插件仍由 DSH 自己加载,移动层负责适配布局与连接,不修改 DeepSeek Harness 源码。
213
214
 
@@ -215,7 +216,7 @@ Android App 将局域网、cpolar、cloudflared、Tailscale Funnel 和自建 FRP
215
216
 
216
217
  代理页面为兼容部分社区插件允许嵌入 HTTP 页面;这类内容未加密,可能被篡改,浏览器也可能因混合内容策略拦截。处理敏感内容时请使用 HTTPS。通过 HTTPS 管理入口打开远程面板时,页面顶部会显示相同提醒。
217
218
 
218
- - 已发布的 0.4.0 按 DSH `0.1.5-rc.2` 做过 renderer-v2 合同检查,并保留对 `0.1.5-rc.1` 局域网路径的验证。DSH 页面需要提供标准的会话、`main`/`panelInfo` 和 `rightbar` 插槽;插件自身需要通过 DSH 的标准面板或侧边栏入口注册内容。
219
+ - 0.4.4 按 DSH `0.1.6-alpha.2` 做 renderer-v2 契约检查。DSH 页面需要提供标准的会话、`main`/`panelInfo` 和 `rightbar` 插槽;插件自身需要通过 DSH 的标准面板或侧边栏入口注册内容。
219
220
  - 网关默认只允许 DSH 内置的第一方 WebSocket 路径。社区侧边栏插件使用的其他路径默认拦截,通常会在诊断页显示为待处理项目;截图中的`/sidebar/ws/agent-opens` 和`/sidebar/ws/agent-terminals` 就属于这类需要按实际插件确认的路径。
220
221
  - 在 **连接诊断 → 第三方 WebSocket 路径** 中,只对确认过的精确路径点击 **允许**。系统不接受带查询字符串或模糊前缀的路径;不建议使用“全部允许”。已允许的路径可以随时移除,局域网和远程连接使用同一套规则。
221
222
  - 放行只代表该路径可以通过已认证、同源的 DSH Mobile 网关,不会开放任意 TCP/UDP 端口,也不会绕过设备配对。若社区插件仍然连接失败,先看诊断页的实际拦截路径,再按一条路径放行。
@@ -268,20 +269,43 @@ flowchart LR
268
269
  - 局域网监听只用于可信家庭、办公网络或可信热点;不要自行做端口转发。
269
270
  - 远程地址可从公网到达,但未配对请求无法进入 DSH;不使用时应关闭远程开关。
270
271
  - cpolar 仅在用户确认后下载固定官方版本并校验大小和 SHA-256;不会安装系统服务、写入 PATH 或设置开机启动,插件清理会删除其托管文件。
271
- - cloudflared 同样仅在用户确认后从官方 GitHub Release 下载固定版本并校验精确大小和 SHA-256,且启动时关闭自动更新,以保证运行的始终是已校验的那份二进制;不需要账号、Token 或 DNS 记录,不写入任何凭据,清理时删除插件托管的全部文件。
272
+ - cloudflared 同样仅在用户确认后从官方 GitHub Release 下载固定版本并校验精确大小和 SHA-256,且启动时关闭自动更新,以保证运行的始终是已校验的那份二进制;快速隧道不需要账号、Token 或 DNS 记录;命名隧道令牌只存插件私有目录、只经环境变量传给 cloudflared,清理时删除插件托管的全部文件。
272
273
  - 自建 FRP 仅在用户确认后从官方 Release 下载固定版本 `frpc`,校验来源、精确大小、SHA-256、压缩包路径和可执行文件版本;共享 Token 不会出现在状态、诊断或日志中。复制服务器模板时 Token 会进入系统剪贴板,请粘贴后及时清除;本机清理只删除插件管理的文件,VPS 需要用面板提供的卸载脚本或一键清理单独清除。自动部署与一键清理前都会展示 SSH 主机指纹,必须到 VPS 控制台核对后才能继续。
273
274
  - 配对设备拥有控制电脑端 DeepSeek Harness 的能力,应视为完全可信设备;丢失手机后应在电脑端撤销设备。
274
275
  - 移动网关开启时才监听局域网;关闭后 DeepSeek Harness 仍正常在电脑本机运行。
275
276
 
276
277
  完整说明见 [SECURITY.md](SECURITY.md)。
277
278
 
279
+ ## 故障排查
280
+
281
+ - **启动报 `saved LAN interface "XXX" is not connected` 且 DSH 起不来**:
282
+ 电脑切换过网络(WiFi/有线/扩展坞),之前保存的网卡当前未连接。处理方式
283
+ (三选一):连回原来的网络;按新网络重跑一遍 setup;暂时不用手机访问时,
284
+ 在 `cordis.patch.yml` 把 `mobile-access` 设 `disabled: true`。新版本中该
285
+ 情况不再阻断启动——插件记一条警告后休眠,等网卡回来自动恢复。
286
+
278
287
  ## 兼容性
279
288
 
280
289
  下表列出各插件版本验证支持到的 DeepSeek Harness 版本(早于该版本的 0.1.x 均兼容)。0.3.6 起插件不再按版本号拒绝启动,未列出的更新版本由 CI 契约检查兜底。历史记录见 [CHANGELOG.md](CHANGELOG.md)。
281
290
 
291
+ ### 系统支持矩阵
292
+
293
+ | 通道 | Windows x64 | Linux x64 | Linux arm64 | macOS |
294
+ | --- | --- | --- | --- | --- |
295
+ | 局域网 | 支持(自动配防火墙) | 支持(防火墙自理) | 支持 | 支持 |
296
+ | Tailscale Funnel | 支持(随包提供) | 支持(随包提供) | 支持(随包提供) | 不支持 |
297
+ | cpolar | 支持(按需下载) | 支持(按需下载) | 支持(按需下载) | 不支持 |
298
+ | cloudflared 快速/命名隧道 | 支持(按需下载) | 支持(按需下载) | 支持(按需下载) | 不支持 |
299
+ | 自建 FRP | 支持(按需下载) | 支持(按需下载) | 支持(按需下载) | 支持(按需下载) |
300
+ | 自有反向代理 | 支持(纯配置) | 支持(纯配置) | 支持(纯配置) | 支持(纯配置) |
301
+
302
+ macOS 上局域网、自建 FRP 与自有反向代理可用;三个托管组件暂未提供 macOS 包。诊断页的防火墙检查目前仅覆盖 Windows,其他系统显示“不适用”。
303
+
282
304
 
283
305
  | DSH Mobile 插件 | 验证支持的 DeepSeek Harness 版本 |
284
306
  | ----------------------------------------- | -------------------------------------------------------------- |
307
+ | `0.4.4` | `0.1.6-alpha.2`(本机源码与 renderer-v2 契约检查) |
308
+ | `0.4.3` | `0.1.6-alpha.2`(本机源码与 renderer-v2 契约检查) |
285
309
  | `0.4.2` | `0.1.6-alpha.1`(本机源码与 renderer-v2 契约检查) |
286
310
  | `0.4.1` | `0.1.6-alpha.1`(本机源码与 renderer-v2 契约检查) |
287
311
  | `0.3.15`、`0.3.16`、`0.4.0` | `0.1.5-rc.2`(契约检查);`0.1.5-rc.1`(@idoall 局域网实测) |
@@ -292,7 +316,7 @@ flowchart LR
292
316
  | `0.3.0`-`0.3.3` | `0.1.2-alpha.1` |
293
317
  | `0.1.4`、`0.2.x` | `0.1.1-rc.2` |
294
318
 
295
- 现有 0.3.3–0.4.0 App 无需重新配对;cpolar 用户应使用 0.3.15 或更新 App,较早版本可能在免费线路的慢速首次加载完成前超时;更早的 App 还使用不同的状态栏策略。App 0.4.0 才支持多设备列表、启动行为设置和电脑端撤销状态同步;旧版 App 仍可连接已保存的单台设备。App 0.1.3 及更早版本需卸载重装并重新配对。
319
+ 现有 App(0.3.3 及更新)无需重新配对;cpolar 用户应使用 0.3.15 或更新 App,较早版本可能在免费线路的慢速首次加载完成前超时;更早的 App 还使用不同的状态栏策略。App 0.4.0 才支持多设备列表、启动行为设置和电脑端撤销状态同步;旧版 App 仍可连接已保存的单台设备。App 0.1.3 及更早版本需卸载重装并重新配对。
296
320
 
297
321
  ## 卸载
298
322
 
@@ -309,6 +333,10 @@ dsh plugin --profile web remove dsh-mobile
309
333
 
310
334
  源码模式把上述 `dsh` 换成 `pnpm dsh`。
311
335
 
336
+ ## 贡献者
337
+
338
+ 感谢提交 PR、复现问题和提出建议的社区成员。[贡献者名单](CONTRIBUTORS.md)按已合并 PR、后来吸收的 PR 工作和 issue 反馈分别致谢;GitHub 右侧的 Contributors 区域由进入默认分支的提交自动生成,不能手动加入仅反馈问题的成员。
339
+
312
340
  ## 开发
313
341
 
314
342
  ```powershell
Binary file
@@ -77,8 +77,8 @@ The old remote entry in the device list will show **Address may have changed** o
77
77
  | Could not reserve a local port | `cloudflared_port_reservation_failed` | Reserving the loopback port failed for a reason other than the port being busy. Retry, and check system resources if it persists. |
78
78
  | Component download failed verification | `cloudflared_download_hash_mismatch` / `cloudflared_download_size_mismatch` | The downloaded binary does not match the pinned size or SHA-256. Install again; repeated failures mean something is rewriting the transfer. |
79
79
  | Installed component failed verification | `cloudflared_executable_hash_mismatch` | The local cloudflared no longer matches the verified build. Remove it completely and install again. |
80
- | This build cannot run the component | `cloudflared_component_unsupported` | The platform is outside the supported set (currently Windows x64 only). |
81
- | Timed out waiting for the tunnel | `cloudflared_start_timeout` | The connector did not print `Registered tunnel connection` within 60 seconds, usually because it cannot reach a Cloudflare edge. |
80
+ | This build cannot run the component | `cloudflared_component_unsupported` | The platform is outside the supported set (currently Windows x64 and Linux x64/arm64). |
81
+ | Timed out waiting for the tunnel | `cloudflared_start_timeout` | The connector did not print `Registered tunnel connection` within the startup budget. In named mode a live connector keeps waiting (up to about 5 minutes); usually it cannot reach a Cloudflare edge. |
82
82
  | Component not installed | `cloudflared_component_missing` | The official component is absent. Complete the preparation steps above. |
83
83
  | Component verification failed | `cloudflared_component_invalid` | The local component does not match the verified build. Remove it completely and install again. |
84
84
  | Could not allocate a port | `cloudflared_port_unavailable` | Quick mode could not allocate the loopback gateway port. Retry. |
@@ -77,8 +77,8 @@
77
77
  | 无法预留本机端口 | `cloudflared_port_reservation_failed` | 本机端口预留本身失败(不是端口被占)。重试;若持续出现请检查系统资源。 |
78
78
  | 组件下载校验失败 | `cloudflared_download_hash_mismatch` / `cloudflared_download_size_mismatch` | 下载到的二进制与固定版本的大小或 SHA-256 不符。重新安装;若反复失败说明中间链路在改包。 |
79
79
  | 已安装组件校验失败 | `cloudflared_executable_hash_mismatch` | 本机那份 cloudflared 与校验过的版本不一致。彻底移除后重新安装。 |
80
- | 当前构建不支持该组件 | `cloudflared_component_unsupported` | 当前平台不在支持范围内(目前仅 Windows x64)。 |
81
- | 等待隧道可用超时 | `cloudflared_start_timeout` | connector 在 60 秒内没有打印 `Registered tunnel connection`。常见原因是网络到 Cloudflare 边缘不通。 |
80
+ | 当前构建不支持该组件 | `cloudflared_component_unsupported` | 当前平台不在支持范围内(目前支持 Windows x64 与 Linux x64/arm64)。 |
81
+ | 等待隧道可用超时 | `cloudflared_start_timeout` | connector 在超时预算内没有打印 `Registered tunnel connection`。命名隧道下进程活着会继续等(最多约 5 分钟);常见原因是网络到 Cloudflare 边缘不通。 |
82
82
  | 组件未安装 | `cloudflared_component_missing` | 还没安装官方组件。按上面的准备步骤安装。 |
83
83
  | 组件校验失败 | `cloudflared_component_invalid` | 本机组件与校验过的版本不符。彻底移除后重新安装。 |
84
84
  | 无法分配端口 | `cloudflared_port_unavailable` | 快速隧道模式下无法分配本机网关端口。重试。 |