dsh-mobile 0.6.6 → 0.6.8

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,6 +2,26 @@
2
2
 
3
3
  Notable changes are recorded here. GitHub Releases provide the downloadable packages and generated commit notes.
4
4
 
5
+ ## 0.6.8 - 2026-10-15
6
+
7
+ - Fix remote pairing on computers with the same default state path overwriting one another in the Android device list. Automatically identified entries without a pairing CA use their persisted random installation identifier for new pairings; explicit operator IDs, LAN CA fingerprints and self-signed FRP CA fingerprints remain unchanged.
8
+ - Read both device-state versions and write version 2 on the next mutation, preserving each new credential's pairing identity. Existing credentials keep their previous native renewal/probe identity during ordinary upgrades with the same state path and gateway configuration, with no wire-protocol change or required Android App update. See [upgrade and downgrade precautions](SECURITY.md#installation-identity-and-device-state-upgrades).
9
+ - Publish the complete installation identifier atomically without replacing an existing one, avoiding a concurrent starter reading an empty file. Refuse invalid identity files and unsupported initial publication rather than silently changing the identity.
10
+ - Keep working pairings without re-pairing. A local App credential already overwritten by the collision cannot be recovered automatically: update and restart the plugin, then pair each affected computer again. Usable old rows remain valid; any duplicate local row can be removed explicitly without computer-side revocation.
11
+ - Adapt compatibility checks to DSH 0.2.1-alpha.3's authenticated Host-backed settings while retaining the Remote/Connection dependency checks and earlier settings policies. Mobile typography remains local to its Origin. Extend the browser test matrix to alpha.3 and recognize its first-run account dialog without submitting credentials.
12
+ - Add bilingual remote-channel selection notes distinguishing the maintainer's long-term network experience from provider limits and conditional self-hosted deployment characteristics.
13
+ - Android App 0.6.3 remains the published native release. The pending Android file-picker changes below are not part of this plugin fix. Thanks @Yurzi for reporting [#213](https://github.com/saya-ch/dsh-mobile/issues/213).
14
+
15
+ ## 0.6.7 - 2026-10-14
16
+
17
+ - Add optional `cpolarSubdomain` and `cpolarRegion` profile settings for a reserved cpolar address. Omitted or blank values keep provider defaults; only the validated HTTPS origin reported by cpolar is used. Existing pairing and authorization checks are unchanged. [Configuration guide](docs/CPOLAR_SUBDOMAIN.en.md).
18
+ - Include complete profile override examples and regressions for configuration-to-process arguments, invalid settings and provider startup failures. This feature does not require an Android App update.
19
+ - Improve narrow-screen sidebar interaction and scrolling with larger panel/footer content. Keep the Workspace list usable and footer actions reachable without enabling the shell overlay as a full-page click target.
20
+ - Load mobile customizations only on their authenticated Gateway entry, including the stock diagnostic page. Add deduplicated Chinese, English and Italian failure/recovery messages, pause unauthorized extension streams, and retain loaded styles and page state through temporary failures without weakening authentication.
21
+ - Ignore a cancelled manifest request before it can clear newer extensions. Preserve the existing custom-file and extension size limits, and keep preview Back handling separate from Gateway API loading.
22
+ - Clarify `/mobile` and both READMEs: detected files are not proof of page activation; ordinary DSH login or phone-sized preview does not establish mobile pairing. Thanks @Dantezcx for the detailed reports in [#209](https://github.com/saya-ch/dsh-mobile/issues/209) and [#210](https://github.com/saya-ch/dsh-mobile/issues/210).
23
+ - Thanks @GavinQiEr for the request in [#207](https://github.com/saya-ch/dsh-mobile/issues/207) and implementation in [#208](https://github.com/saya-ch/dsh-mobile/pull/208); the original author commit is retained alongside maintainer corrections.
24
+
5
25
  ## Unreleased Android changes
6
26
 
7
27
  - Prefer the system Photo Picker on Android 13+ for supported image requests, with document selection for other requests or an unavailable picker. Preserve multi-selection, MIME filtering and selected URI results without adding storage permission or forcing a vendor gallery.
package/CONTRIBUTORS.md CHANGED
@@ -4,6 +4,12 @@ GitHub 的 [Contributors 图表](https://github.com/saya-ch/dsh-mobile/graphs/co
4
4
 
5
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-10-14. The repository maintainer and automated dependency updates remain visible in GitHub's history.
6
6
 
7
+ ## 0.6.7 代码贡献 / Code contributions in 0.6.7
8
+
9
+ [@GavinQiEr](https://github.com/GavinQiEr) 在 [#207](https://github.com/saya-ch/dsh-mobile/issues/207) 提出 cpolar 固定子域名支持,并在 [#208](https://github.com/saya-ch/dsh-mobile/pull/208) 提供配置、启动参数和文档实现。[#211](https://github.com/saya-ch/dsh-mobile/pull/211) 的整合保留原作者提交 [`8dd7574`](https://github.com/saya-ch/dsh-mobile/commit/8dd75749d3823aecafdb6f5d9faccf674577e7b1),并追加维护者修正,纳入 0.6.7。
10
+
11
+ [@GavinQiEr](https://github.com/GavinQiEr) requested reserved cpolar subdomains in [#207](https://github.com/saya-ch/dsh-mobile/issues/207) and implemented the configuration, process arguments and guides in [#208](https://github.com/saya-ch/dsh-mobile/pull/208). Integration [#211](https://github.com/saya-ch/dsh-mobile/pull/211) retains author commit [`8dd7574`](https://github.com/saya-ch/dsh-mobile/commit/8dd75749d3823aecafdb6f5d9faccf674577e7b1) alongside maintainer corrections for 0.6.7.
12
+
7
13
  ## 0.6.4 代码贡献 / Code contributions in 0.6.4
8
14
 
9
15
  [@abworks-dev](https://github.com/abworks-dev) 的 [#200](https://github.com/saya-ch/dsh-mobile/pull/200) 提供窄屏输入栏包装层与按钮点击区域的尺寸修正及回归测试,代码已随 0.6.4 发布;随后以合并提交 [`71754e5`](https://github.com/saya-ch/dsh-mobile/commit/71754e5191d3e9eadfedad16982e144491272f26) 保留原作者提交 [`03604ae`](https://github.com/saya-ch/dsh-mobile/commit/03604ae7623ceb42090ff4c4ed0e84d4aff7144a)。这次历史补全不改变已发布的功能或标签。
@@ -58,6 +64,10 @@ GitHub's Contributors graph counts commits on the default branch; issue reports
58
64
 
59
65
  ## 问题反馈与建议 / Issue reports and ideas
60
66
 
67
+ 感谢 [@Yurzi](https://github.com/Yurzi) 在 [#213](https://github.com/saya-ch/dsh-mobile/issues/213) 报告不同电脑的远程配对记录互相覆盖。 / Thanks [@Yurzi](https://github.com/Yurzi) for reporting remote pairing records on different computers overwriting one another in [#213](https://github.com/saya-ch/dsh-mobile/issues/213).
68
+
69
+ 感谢 [@Dantezcx](https://github.com/Dantezcx) 在 [#209](https://github.com/saya-ch/dsh-mobile/issues/209) 和 [#210](https://github.com/saya-ch/dsh-mobile/issues/210) 提供侧栏命中、短屏布局和定制资源加载的详细诊断。 / Thanks [@Dantezcx](https://github.com/Dantezcx) for the detailed sidebar hit-testing, short-viewport and customization-loading diagnostics in [#209](https://github.com/saya-ch/dsh-mobile/issues/209) and [#210](https://github.com/saya-ch/dsh-mobile/issues/210).
70
+
61
71
  感谢 [@xhwxt](https://github.com/xhwxt) 在 [#203](https://github.com/saya-ch/dsh-mobile/pull/203) 中提出文档选择器改进方案,以及 [@Void-LifeStream](https://github.com/Void-LifeStream) 在 [#205](https://github.com/saya-ch/dsh-mobile/issues/205) 中提供附件选择与回传问题的详细反馈。
62
72
 
63
73
  Thanks [@xhwxt](https://github.com/xhwxt) for the document-picker proposal in [#203](https://github.com/saya-ch/dsh-mobile/pull/203), and [@Void-LifeStream](https://github.com/Void-LifeStream) for the detailed attachment-selection and delivery report in [#205](https://github.com/saya-ch/dsh-mobile/issues/205).
@@ -112,5 +122,5 @@ Thanks [@xhwxt](https://github.com/xhwxt) for the document-picker proposal in [#
112
122
  | [@tianyimc](https://github.com/tianyimc) | [#126](https://github.com/saya-ch/dsh-mobile/issues/126) |
113
123
  | [@Xingcheng-wang](https://github.com/Xingcheng-wang) | [#76](https://github.com/saya-ch/dsh-mobile/issues/76) |
114
124
  | [@xhwxt](https://github.com/xhwxt) | [#107](https://github.com/saya-ch/dsh-mobile/issues/107), [#108](https://github.com/saya-ch/dsh-mobile/issues/108), [#145](https://github.com/saya-ch/dsh-mobile/issues/145), [#146](https://github.com/saya-ch/dsh-mobile/issues/146), [#149](https://github.com/saya-ch/dsh-mobile/issues/149), [#171](https://github.com/saya-ch/dsh-mobile/issues/171) |
115
- | [@Yurzi](https://github.com/Yurzi) | [#17](https://github.com/saya-ch/dsh-mobile/issues/17) |
125
+ | [@Yurzi](https://github.com/Yurzi) | [#17](https://github.com/saya-ch/dsh-mobile/issues/17), [#213](https://github.com/saya-ch/dsh-mobile/issues/213) |
116
126
  | [@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
@@ -25,13 +25,13 @@
25
25
  <a href="#security">Security</a> ·
26
26
  <a href="#compatibility">Compatibility</a> ·
27
27
  <a href="#contributors">Contributors</a> ·
28
- <a href="CHANGELOG.md">Changelog</a> ·
28
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.8">Release notes</a> ·
29
29
  <a href="README.md">简体中文</a>
30
30
  </p>
31
31
 
32
32
  > DSH Mobile is a DeepSeek Harness community plugin; the native app supports Android only.
33
33
  >
34
- > **Current stable release: 0.6.6**. Fix captured images not reaching the DSH attachment draft, and improve cancellation and late-result handling in browser file selection. [Changelog](CHANGELOG.md) · [Release downloads](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.6).
34
+ > **Current stable release: 0.6.8**. Fix computers with the same default state path overwriting one another in the App device list, adapt to DSH 0.2.1-alpha.3, and add remote-channel selection guidance. Working pairings stay valid; an App update is not required. [Release notes and downloads](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.8) · [Full changelog](CHANGELOG.md).
35
35
  >
36
36
  > **Version policy**: since plugin **0.6.2**, the Android app and plugin use independent version numbers and releases. Their numbers do not need to match, and a plugin update does not imply an app update. [Compatibility notes](#compatibility).
37
37
 
@@ -152,14 +152,16 @@ Remote providers may impose bandwidth and connection limits: the [cpolar Free pl
152
152
 
153
153
  If the page opens but stays on “Reconnecting,” distinguish WebSocket upgrade failures, slow synchronization, and heartbeat deadlines using the [slow-link and reconnection guide](docs/SLOW_CONNECTIONS.en.md). Version 0.5.4 also offers opt-in WebSocket compression per exact path, disabled by default; for long Sessions or metered links, follow the guide and compare actual transfer volume.
154
154
 
155
- | Channel | Prerequisites | Address and limitation |
156
- | --- | --- | --- |
157
- | cpolar | Account and Authtoken | An option to try on mainland networks; free temporary URLs may change |
158
- | cloudflared quick tunnel | No account or domain | Random temporary URL; no SSE, with [notification limits](docs/CLOUDFLARE_TUNNEL.en.md#quick-tunnel-feature-limits) |
159
- | cloudflared named tunnel | Cloudflare account and domain | Fixed hostname; [setup guide](docs/CLOUDFLARE_TUNNEL.en.md) |
160
- | Tailscale Funnel | Sign-in and Funnel authorization | May be unreliable on mainland-China networks |
161
- | Self-hosted FRP | VPS and domain or real public IPv4 | Server maintenance required; [deploy](docs/SELF_HOSTED_FRP.en.md) or [attach to existing frps](docs/ATTACH_EXISTING_FRPS.en.md) |
162
- | Own reverse proxy | Existing public HTTPS proxy | The plugin provides only its private authenticated backend; [guide](docs/SELF_HOSTED_ORIGIN.en.md) |
155
+ The usage notes below reflect the maintainer's long-term experience on a personal mainland-China network, not a universal comparison. Performance depends on the carrier, network and plan; verify the route on your own phone's network.
156
+
157
+ | Channel | Prerequisites | Address and limitation | Maintainer's usage notes |
158
+ | --- | --- | --- | --- |
159
+ | cpolar | Account and Authtoken | Free temporary URLs may change | The free plan's bandwidth limit noticeably slows everyday loading and synchronization |
160
+ | cloudflared quick tunnel | No account or domain | Random temporary URL; no SSE, with [notification limits](docs/CLOUDFLARE_TUNNEL.en.md#quick-tunnel-feature-limits); [officially intended only for development and testing](https://developers.cloudflare.com/tunnel/get-started/quick-tunnels/) | Frequent disconnections in long-term use, with the cause still unconfirmed; a temporary or testing choice |
161
+ | cloudflared named tunnel | Cloudflare account and domain | Fixed hostname; [setup guide](docs/CLOUDFLARE_TUNNEL.en.md) | The most stable of the channels used long-term; worth trying first if you have an account and domain |
162
+ | Tailscale Funnel | Sign-in and Funnel authorization | Availability depends on the network | This personal network often needs proxy assistance and may still fail to connect; not every user needs a proxy |
163
+ | Self-hosted FRP | VPS and domain or real public IPv4 | Server maintenance required; [deploy](docs/SELF_HOSTED_FRP.en.md) or [attach to existing frps](docs/ATTACH_EXISTING_FRPS.en.md) | More control over deployment and resources; long-term stability depends on the VPS route, configuration and maintenance |
164
+ | Own reverse proxy | Existing public HTTPS proxy | The plugin provides only its private authenticated backend; [guide](docs/SELF_HOSTED_ORIGIN.en.md) | Reuses your proxy infrastructure; stability depends on the proxy, network route and maintenance |
163
165
 
164
166
  <p align="center">
165
167
  <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/remote-access-en.png" width="82%" alt="DSH Mobile remote access and provider selection">
@@ -188,7 +190,7 @@ After selecting the channel in the panel:
188
190
 
189
191
  > **Remote notifications**: browser `Notification` permission is granted per Origin, and a web-page system toast appears only on the device running that page. Android task reminders are a separate 0.4.0 feature: enable them under DSH **Settings → General** in the app, and keep the WebView page alive; they are not a general background push service. For reliable background delivery, use a server-side webhook or bot channel you have configured.
190
192
 
191
- Tailscale Funnel has broad reach but may be unreliable from mainland China. Its runtime ties the public listener to the parent process and a bounded control channel; parent exit, channel closure, or an explicit stop ends the current generation and cleans up its resources. cpolar is better suited to mainland networks, while self-hosted FRP fits users who already have a VPS and want to avoid public-provider bandwidth quotas. cloudflared runs in two modes: a quick tunnel needs no account or sign-in, but its hostname is random, changes on every reconnect, and is [intended by Cloudflare for testing](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/trycloudflare/) without an uptime guarantee, so it suits temporary or verification use rather than a permanent channel; a named tunnel uses a Cloudflare account token and keeps one fixed public hostname across restarts. An unregistered domain on a mainland-China VPS may be intercepted by the cloud provider; public IPv4 mode avoids that dependency. The plugin validates pinned on-demand components; locally managed configuration and binaries live under `$DSH_HOME/mobile-access/` and can be cleaned up from the panel. VPS files require separate cleanup through the self-hosted connection guide.
193
+ The Funnel runtime ties the public listener to the parent process and a bounded control channel; parent exit, channel closure, or an explicit stop ends the current generation and cleans up its resources. An unregistered domain on a mainland-China VPS may be intercepted by the cloud provider; public IPv4 mode avoids that dependency. The plugin validates pinned on-demand components; locally managed configuration and binaries live under `$DSH_HOME/mobile-access/` and can be cleaned up from the panel. VPS files require separate cleanup through the self-hosted connection guide.
192
194
 
193
195
  Managed self-hosted FRP uses an HTTP vhost to the DSH loopback gateway. Its plaintext VPS listener must be loopback-only, with Caddy providing public HTTPS. Version 0.4.6 adds existing-frps attachment without installing or changing the server: its public-CA mode still needs a restricted HTTP vhost and Caddy, while its self-signed mode forwards raw TCP to a computer-side HTTPS gateway whose CA the 0.4.6 Android app pins during pairing. The self-signed mode currently uses public IPv4 and is unavailable to older apps. Neither mode exposes arbitrary FRP configuration. Because frps `proxyBindAddr` governs proxy listeners globally, do not change it for the new TCP entry without checking existing plaintext vhosts. See the [attachment guide](docs/ATTACH_EXISTING_FRPS.en.md).
194
196
 
@@ -212,7 +214,9 @@ It can also drive computer capabilities the phone can use, like reading the mach
212
214
  /mobile give the phone a cyberpunk-style computer monitor panel that shows live CPU, memory, and disk usage
213
215
  ```
214
216
 
215
- Two kinds of changes are supported: the phone UI itself (theme, layout, buttons), and computer capabilities the phone can use (browsing computer files, running programs on the computer). `/mobile` hands the request to the DSH agent, which edits files under the local DSH configuration directory (`$DSH_HOME/mobile-access/`); the phone client applies them automatically. UI changes live in `mobile.css`/`mobile.js`. Computer capabilities come from extensions under `extensions/`, whose `host.mjs` runs with the local user's privileges on the computer. DeepSeek Harness source is not modified.
217
+ Two kinds of changes are supported: the phone UI itself (theme, layout, buttons), and computer capabilities the phone can use (browsing computer files, running programs on the computer). `/mobile` hands the request to the DSH agent, which edits files under the local DSH configuration directory (`$DSH_HOME/mobile-access/`); paired mobile pages automatically check and apply them. UI changes live in `mobile.css`/`mobile.js`. Computer capabilities come from extensions under `extensions/`, whose `host.mjs` runs with the local user's privileges on the computer. DeepSeek Harness source is not modified.
218
+
219
+ Open customizations through the **Mobile Access pairing entry**. Opening an ordinary DSH page or selecting a phone-sized browser viewport is not mobile pairing, and a file's presence does not establish that the current page loaded it. If extension requests return `401`, check the entry and pairing state; do not enable anonymous access or share Cookies or Tokens.
216
220
 
217
221
  Extension manifests, scripts, styles, and assets are revisioned. When the plugin observes a `/mobile` or extension-file change, it notifies authenticated phones to refresh immediately; 45-second visible and 5-minute hidden checks remain only as recovery fallbacks. A failed Host staging pass keeps the current version; if the Host has changed but the new phone UI cannot activate, that extension closes and retries instead of mixing generations.
218
222
 
@@ -237,6 +241,8 @@ The examples above, applied:
237
241
 
238
242
  The Android app lists computers and their LAN/remote records under **Paired computers**. The two authorization types remain separate, so one computer can have two rows. Upgrades migrate old credentials without re-pairing; after a changed address is verified, matching identities merge and keep their names. Self-signed FRP uses a separate CA fingerprint and may create another row. Android Keystore encrypts tokens and pinned CAs. A pairing QR code contains temporary pairing information, never a long-lived device token or CA private key.
239
243
 
244
+ Unless an identifier is configured manually, new pairings through a public-certificate remote entry use a random identifier saved on the computer, preventing identical installation paths from overwriting another computer's row. Working connections need no re-pairing or Android App update; LAN and self-signed FRP still use their respective CAs. Quit DSH normally and restart after updating; read the [state-backup precautions](SECURITY.md#installation-identity-and-device-state-upgrades) before downgrading.
245
+
240
246
  Each row shows its custom name, transport, Origin, periodically refreshed 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.
241
247
 
242
248
  - **Startup behavior → Open DSH directly** (default): one device connects directly; with multiple devices, the app tries the last-used device first, then the still-valid device with the most recent connection. A bounded connection budget returns to the list instead of spinning forever.
@@ -321,7 +327,7 @@ Selection priority is device choice → computer defaults → plugin configurati
321
327
  | Android app | Everyday use | Separate Local and Remote entries at first pairing; LAN discovery, system trust for public remote certificates, and app-pinned CA for the self-signed FRP entry |
322
328
  | Mobile browser | Temporary or cross-platform | Open the HTTPS origin shown by Mobile Access; a private LAN certificate may need confirmation, while a public remote certificate should not warn |
323
329
 
324
- The Android app is a thin Kotlin WebView shell and contains no frontend copy; mobile browsers load the same page. Developers can append `?frontend=stock` to an authenticated mobile URL to compare the stock layout. This diagnostic entry bypasses mobile enhancements and module selection; some API operations may be rejected, so it does not replace normal mobile access. See [skins and mobile layout](docs/SKIN_COMPATIBILITY.en.md).
330
+ The Android app is a thin Kotlin WebView shell and contains no frontend copy; mobile browsers load the same page. Developers can append `?frontend=stock` to an authenticated mobile URL to diagnose boot and layout behavior. This entry skips dedicated mobile boot rewriting and module selection, but installed client adaptation and authenticated customizations may still apply. It is not a plugin-free control; some API operations may be rejected, so it does not replace normal mobile access. See [skins and mobile layout](docs/SKIN_COMPATIBILITY.en.md).
325
331
 
326
332
  In 0.5.5, the dedicated mobile page synchronously loads the authenticated, same-origin `/mobile-access/compat.js` before the first DSH boot script. This bundled core-js compatibility layer supplies `Iterator` / Iterator helpers to WebViews that lack them, preventing the startup error `Iterator is not defined`. It uses feature detection to preserve or repair native helpers, needs no CDN, and does not weaken CSP. The desktop and `?frontend=stock` pages do not load this gateway script.
327
333
 
@@ -359,6 +365,7 @@ See [SECURITY.md](SECURITY.md).
359
365
 
360
366
  ## Troubleshooting
361
367
 
368
+ - **Pairing a second computer overwrites the first**: see [#213](https://github.com/saya-ch/dsh-mobile/issues/213). Update to plugin 0.6.8 or newer, restart DSH normally, then scan each affected computer's current QR code. An App credential already overwritten cannot be recovered automatically; working old rows need no re-pairing. If the same address has both an old and a new row, confirm the new one works, then delete only the extra local App row. Do not reset remote access. Read the [device-state backup and downgrade precautions](SECURITY.md#installation-identity-and-device-state-upgrades) before upgrading.
362
369
  - **Pairing succeeds but renewal returns `401` or repeatedly asks to pair again**: other services on the same hostname or stale Cookies may interfere with authentication. Update to the latest plugin and app, then retry through the current Mobile Access entry. In a browser, scanning the current QR code again refreshes this plugin's authentication Cookies without clearing all website data. If it still fails, inspect the failed request and sanitized logs; other authentication or proxy errors can also return `401`.
363
370
  - **The testing notice cannot be confirmed or settings cannot be saved**: open DSH directly at its local address on the computer, then inspect the terminal log or the failed settings request in the browser's Network panel. Connection diagnostics do not test settings writes. Keep the existing configuration and `settings.yaml.imported`, and investigate the specific error; the same UI message can have different causes. See [DSH #860](https://github.com/deepseek-ai/deepseek-harness/discussions/860).
364
371
  - **A settings request returns HTTP `403`**: first inspect DSH's Host/Origin trust checks and any proxy response. Check whether an iframe, proxy, or browser extension changes the request's origin, and verify direct local access. Keep the trust checks enabled.
@@ -397,6 +404,7 @@ On macOS, local network, cloudflared, self-hosted FRP and the own reverse proxy
397
404
  | `0.6.4` | `0.2.0-rc.2` (packed installation, isolated pairing, mobile boot and WebSocket Workspace reads); additionally 72 real public-slot composer layouts, Windows Desktop directory-picker composition and cross-platform regressions. The reported remote timeout in community Desktop 2.0.17 remains unclaimed as accepted |
398
405
  | `0.6.5` | Packed module-management and mobile-settings regressions on `0.2.0-rc.2` and `0.2.1-alpha.2`; additionally Windows cpolar extraction and populated Trajectory layout with published `maid-atelier` 0.1.7. This does not establish acceptance of every third-party skin or reporter device |
399
406
  | `0.6.6` | Packed attachment intake and decoded-preview regressions on `0.2.0-rc.2` and `0.2.1-alpha.2`, covering multiple images, cancellation, late results and superseded requests. Android system-picker changes are released independently, not through the npm update |
407
+ | `0.6.8` | Packed mobile boot, legacy-WebView API simulation, WebSocket Workspace reads, mobile settings, module management, sidebar and composer regressions on `0.2.1-alpha.3`; separate real HTTP/TLS and legacy-credential upgrade tests cover the identity fix. The local official Desktop `0.2.0-rc.2` loads this plugin version with existing pairings preserved. This does not establish phone cellular or every third-party plugin combination |
400
408
 
401
409
  <details>
402
410
  <summary>Historical version checks</summary>
package/README.md CHANGED
@@ -25,13 +25,13 @@
25
25
  <a href="#安全">安全</a> ·
26
26
  <a href="#兼容性">兼容性</a> ·
27
27
  <a href="#贡献者">贡献者</a> ·
28
- <a href="CHANGELOG.md">更新记录</a> ·
28
+ <a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.8">更新记录</a> ·
29
29
  <a href="README.en.md">English</a>
30
30
  </p>
31
31
 
32
32
  > DSH Mobile 是 DeepSeek Harness 社区插件,原生 App 仅支持 Android。
33
33
  >
34
- > **当前正式版本:0.6.6**。修复拍照图片无法进入 DSH 附件草稿的问题,改善浏览器文件选择的取消与迟到结果处理。[更新记录](CHANGELOG.md) · [版本下载](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.6)。
34
+ > **当前正式版本:0.6.8**。修复相同默认状态路径的电脑在 App 设备列表中相互覆盖的问题,适配 DSH 0.2.1-alpha.3,并补充远程通道选择建议。已有正常配对无需重建,也不需要升级 App。[更新与下载](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.8) · [完整更新记录](CHANGELOG.md)。
35
35
  >
36
36
  > **版本说明**:自插件 **0.6.2** 起,Android App 与插件独立编号、独立发布,版本号无需一致;插件升级不代表 App 需要同步升级。[兼容说明](#兼容性)。
37
37
 
@@ -152,14 +152,16 @@ dsh plugin --profile web add dshmarket
152
152
 
153
153
  页面能打开但一直“重连中”,应先区分 WebSocket 升级失败、慢速数据同步和心跳超时,操作见[慢链路与反复重连指南](docs/SLOW_CONNECTIONS.md)。0.5.4 还提供按确切路径启用的 WebSocket 压缩,默认关闭;长会话或计量网络可按指南尝试,并对比实际传输量。
154
154
 
155
- | 连接方式 | 需要准备 | 地址特点与注意事项 |
156
- | --- | --- | --- |
157
- | cpolar | cpolar 账号与 Authtoken | 国内网络可优先尝试;免费临时地址可能变化 |
158
- | cloudflared 快速隧道 | 无需账号或域名 | 临时随机地址;不支持 SSE,[即时通知存在限制](docs/CLOUDFLARE_TUNNEL.md#快速隧道的功能限制) |
159
- | cloudflared 命名隧道 | Cloudflare 账号与域名 | 固定域名;[配置指南](docs/CLOUDFLARE_TUNNEL.md) |
160
- | Tailscale Funnel | Tailscale 登录与 Funnel 授权 | 中国大陆网络可能不稳定 |
161
- | 自建 FRP | 已有 VPS,域名或真实公网 IPv4 | 需管理服务器;[部署](docs/SELF_HOSTED_FRP.md)或[接入既有 frps](docs/ATTACH_EXISTING_FRPS.md) |
162
- | 自有反向代理 | 已有公开 HTTPS 代理 | 插件只提供私有认证后端;[配置指南](docs/SELF_HOSTED_ORIGIN.md) |
155
+ 下表的使用参考来自维护者在中国大陆自用网络的长期体验,不是普适测评;实际表现受运营商、网络和套餐影响,请在自己的手机网络验证。
156
+
157
+ | 连接方式 | 需要准备 | 地址特点与注意事项 | 维护者使用参考 |
158
+ | --- | --- | --- | --- |
159
+ | cpolar | cpolar 账号与 Authtoken | 免费临时地址可能变化 | 免费方案限速明显,日常加载与同步体验较差 |
160
+ | cloudflared 快速隧道 | 无需账号或域名 | 临时随机地址;不支持 SSE,[即时通知存在限制](docs/CLOUDFLARE_TUNNEL.md#快速隧道的功能限制);[官方仅定位为开发测试用途](https://developers.cloudflare.com/tunnel/get-started/quick-tunnels/) | 长期使用中经常断连,原因尚未确认;只作临时或测试选择 |
161
+ | cloudflared 命名隧道 | Cloudflare 账号与域名 | 固定域名;[配置指南](docs/CLOUDFLARE_TUNNEL.md) | 已长期使用的通道中最稳定;有账号和域名可优先尝试 |
162
+ | Tailscale Funnel | Tailscale 登录与 Funnel 授权 | 实际可用性取决于网络 | 自用网络常需代理辅助,仍可能连接失败;并非所有用户都需要代理 |
163
+ | 自建 FRP | 已有 VPS,域名或真实公网 IPv4 | 需管理服务器;[部署](docs/SELF_HOSTED_FRP.md)或[接入既有 frps](docs/ATTACH_EXISTING_FRPS.md) | 部署与资源更可控,长期稳定性取决于 VPS 线路、配置与运维 |
164
+ | 自有反向代理 | 已有公开 HTTPS 代理 | 插件只提供私有认证后端;[配置指南](docs/SELF_HOSTED_ORIGIN.md) | 可沿用自己的代理设施,稳定性取决于代理、线路与运维 |
163
165
 
164
166
  <p align="center">
165
167
  <img src="https://raw.githubusercontent.com/saya-ch/dsh-mobile/main/assets/screenshots/remote-access.png" width="82%" alt="DSH Mobile 远程访问与通道选择">
@@ -188,7 +190,7 @@ dsh plugin --profile web add dshmarket
188
190
 
189
191
  > **远程通知说明**:浏览器的 `Notification` 权限按 Origin 分别授权,网页系统通知只显示在运行该网页的设备上。Android App 的任务提醒是独立的 0.4.0 功能,需要在 App 内 DSH 的 **设置 → 通用设置** 中主动开启,且依赖 WebView 页面仍存活;它不是通用的后台推送。需要可靠的后台推送时,请使用你已配置的服务端 webhook 或机器人通道。
190
192
 
191
- Tailscale Funnel 覆盖范围广,但在中国大陆网络下可能不稳定。其运行组件把公开监听生命周期绑定到父进程和受限控制通道;父进程退出、控制通道关闭或显式停止时会结束当前代次并清理资源。cpolar 更适合国内网络;自建 FRP 适合已有 VPS、希望避开公共服务带宽限制的用户。cloudflared 有两种模式:快速隧道不需要账号或登录,但地址随机、每次重连都会变化,[官方定位为测试用途](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/do-more-with-tunnels/trycloudflare/)且无可用性保证,因此只适合临时或验证场景;命名隧道使用 Cloudflare 账号令牌,能保留重启后不变的固定公网域名。中国大陆 VPS 上的未备案域名可能被云厂商拦截,此时可使用公网 IPv4 模式。插件会校验按需下载的固定版本组件;本机托管的配置与程序保存在 `$DSH_HOME/mobile-access/`,可在面板中清理。VPS 侧的文件须按自建连接指南单独清理。
193
+ Funnel 的运行组件把公开监听生命周期绑定到父进程和受限控制通道;父进程退出、控制通道关闭或显式停止时会结束当前代次并清理资源。中国大陆 VPS 上的未备案域名可能被云厂商拦截,此时可使用公网 IPv4 模式。插件会校验按需下载的固定版本组件;本机托管的配置与程序保存在 `$DSH_HOME/mobile-access/`,可在面板中清理。VPS 侧的文件须按自建连接指南单独清理。
192
194
 
193
195
  自建 FRP 的托管部署使用指向 DSH 回环网关的 HTTP vhost:VPS 上的明文 vhost 只允许回环访问,由 Caddy 提供公网 HTTPS。0.4.6 新增“接入既有 frps”,不会安装或改动服务器;公开 CA 档仍需受限 HTTP vhost 与 Caddy,自签档则用 frps TCP 透传至电脑端 HTTPS 网关,须由 0.4.6 Android App 在配对时固定 CA。自签档目前面向公网 IPv4,旧版 App 不支持;两档都不开放任意 FRP 配置。frps 的 `proxyBindAddr` 是全局代理监听设置,不能只为新增 TCP 入口调整而忽略已有明文 vhost。[接入指南](docs/ATTACH_EXISTING_FRPS.md)。
194
196
 
@@ -212,7 +214,9 @@ Tailscale Funnel 覆盖范围广,但在中国大陆网络下可能不稳定。
212
214
  /mobile 为手机端添加赛博朋克风格的电脑监控面板,实时显示电脑的 CPU、内存和磁盘占用
213
215
  ```
214
216
 
215
- `/mobile` 把需求交给 DSH 对话中的 agent,由它直接修改本机 `$DSH_HOME/mobile-access/` 下的文件,保存后手机端自动生效。改动分两类:界面和交互在 `mobile.css`/`mobile.js`;需要电脑能力时用 `extensions/` 下的扩展,其 `host.mjs` 以本机用户权限在电脑上运行。不修改 DeepSeek Harness 源码。
217
+ `/mobile` 把需求交给 DSH 对话中的 agent,由它直接修改本机 `$DSH_HOME/mobile-access/` 下的文件,已配对的移动页面会自动检查并应用。改动分两类:界面和交互在 `mobile.css`/`mobile.js`;需要电脑能力时用 `extensions/` 下的扩展,其 `host.mjs` 以本机用户权限在电脑上运行。不修改 DeepSeek Harness 源码。
218
+
219
+ 定制需要从 **移动访问的配对入口**进入。直接打开普通 DSH 网页或调整浏览器为手机视口,不等于完成移动配对;文件存在也不代表当前页面已加载。若扩展接口返回 `401`,先核对入口与配对状态,不要开放匿名访问或公开 Cookie、Token。
216
220
 
217
221
  扩展清单及其脚本、样式和资源按版本标识刷新。插件监听到 `/mobile` 或扩展文件变化后,会通过已认证连接通知手机立即更新;页面可见时每 45 秒、隐藏时每 5 分钟的检查只作为断线兜底。Host 暂存失败会继续使用现有版本;若 Host 已更新但新手机界面激活失败,则关闭该扩展并自动重试,避免混用新旧能力。
218
222
 
@@ -237,6 +241,8 @@ Tailscale Funnel 覆盖范围广,但在中国大陆网络下可能不稳定。
237
241
 
238
242
  Android App 在“已配对设备”中统一显示电脑及其局域网/远程连接记录。两种方式的授权彼此独立,同一台电脑可能有两条记录。升级会迁移旧凭据,无需重新配对;重新验证变化的地址后,相同身份的记录会合并并保留名称。自签 FRP 使用独立 CA 指纹,可能另成一条记录。Token 和固定的 CA 由 Android Keystore 加密;配对二维码含短期配对信息,不含长期设备 Token 或 CA 私钥。
239
243
 
244
+ 未手动指定标识时,公开证书远程入口的新配对使用电脑保存的随机标识,避免相同安装路径让两台电脑的记录互相覆盖。已有连接无需为此重新配对,也不需要更新 Android App;局域网和自签 FRP 仍按各自的 CA 区分。更新后正常退出并重启 DSH,降级前请先阅读[状态备份注意事项](SECURITY.md#installation-identity-and-device-state-upgrades)。
245
+
240
246
  每条记录显示自定义名称、连接方式、Origin、定期更新的可达状态和最近连接时间。绿色状态点表示“可达”,灰色状态点表示“检测中”“暂不可达”“配对已过期”或“电脑端已移除”;可达性检查直接验证 DSH Gateway,不依赖 ICMP,也不会把暂时断网误判成电脑端撤销。
241
247
 
242
248
  - **启动行为 → 直接进入 DSH**(默认):单设备直接连接;多设备优先连接上次使用的设备,其次按最近连接时间选择仍有效的设备。连接超过有限重试预算后自动回到列表,不会无限转圈。
@@ -321,7 +327,7 @@ excludedClientModules:
321
327
  | Android App | 日常使用 | 首次配对时分别提供局域网与远程入口;局域网自动发现,公开远程证书由系统验证,自签 FRP 入口由 App 固定 CA |
322
328
  | 手机浏览器 | 临时或跨平台访问 | 打开“移动访问”卡片显示的 HTTPS 地址;局域网私有证书可能需要手动确认,公开远程证书不应出现警告 |
323
329
 
324
- Android App 只是 Kotlin WebView 薄壳,不内置另一份网页;手机浏览器访问的是同一页面。开发者可在已认证移动地址后追加 `?frontend=stock` 对照原生布局;该诊断入口绕过移动增强和模块选择,部分 API 操作可能被拒绝,不能代替正常移动入口。详见[皮肤与移动布局](docs/SKIN_COMPATIBILITY.md)。
330
+ Android App 只是 Kotlin WebView 薄壳,不内置另一份网页;手机浏览器访问的是同一页面。开发者可在已认证移动地址后追加 `?frontend=stock` 诊断启动与布局行为;该入口跳过专用移动启动改写和模块选择,但仍可能加载客户端移动适配及已认证定制,并非不含插件的对照页。部分 API 操作可能被拒绝,不能代替正常移动入口。详见[皮肤与移动布局](docs/SKIN_COMPATIBILITY.md)。
325
331
 
326
332
  0.5.5 的专用移动页面会在 DSH 的第一个启动脚本之前,同步加载经网关鉴权的同源 `/mobile-access/compat.js`,为缺少 `Iterator` / Iterator helpers 的 WebView 提供随插件打包的 core-js 兼容实现,避免启动时出现 `Iterator is not defined`。兼容层按能力检测保留或修正原生 helper,不依赖 CDN,也不会放宽 CSP;桌面页面与 `?frontend=stock` 页面不会加载这个网关脚本。
327
333
 
@@ -360,6 +366,7 @@ flowchart LR
360
366
 
361
367
  ## 故障排查
362
368
 
369
+ - **配对第二台电脑后,第一台被覆盖**:见 [#213](https://github.com/saya-ch/dsh-mobile/issues/213);请升级至插件 0.6.8 或更新版本并正常重启 DSH,再分别扫描受影响电脑当前的二维码。已经被覆盖的 App 本地凭据不能自动找回;仍可连接的旧条目无需重配。若同一地址出现新旧两条记录,确认新条目正常后,只删除 App 中多余的本地条目,不要重置远程访问。升级前请阅读[设备状态备份与降级注意事项](SECURITY.md#installation-identity-and-device-state-upgrades)。
363
370
  - **配对成功后仍反复提示重新配对或续期 `401`**:同一域名上的其他服务或旧 Cookie 可能干扰认证。更新至最新插件及 App,再从当前移动访问入口重试;浏览器重新扫描当前二维码可更新本插件的认证 Cookie,无需清除所有网站数据。若仍失败,查看失败请求与脱敏日志,其他认证或代理错误也可能返回 `401`。
364
371
  - **内测声明无法确认或设置无法保存**:先在电脑端直接打开 DSH 的本机地址,查看终端日志或浏览器 Network 中失败的设置请求。连接诊断不检查设置写入;保留现有配置及 `settings.yaml.imported`,按具体错误排查。相同界面提示可能有不同原因,见 [DSH #860](https://github.com/deepseek-ai/deepseek-harness/discussions/860)。
365
372
  - **设置请求返回 HTTP `403`**:先检查 DSH 的 Host/Origin 信任校验及代理响应。检查 iframe、代理和浏览器扩展是否改变请求来源,使用本机直接访问验证;保持信任检查启用。
@@ -398,6 +405,7 @@ macOS 上局域网、cloudflared、自建 FRP 与自有反向代理可用;Funn
398
405
  | `0.6.4` | `0.2.0-rc.2`(打包安装、隔离配对、移动页面与 WebSocket 工作区读取);另验证 72 组真实公共插槽输入栏布局、Windows Desktop 目录选择器组合及跨平台回归。社区 Desktop 2.0.17 的原报告远程超时仍未宣称验收 |
399
406
  | `0.6.5` | `0.2.0-rc.2`、`0.2.1-alpha.2` 的打包模块管理与移动设置回归;另验证 Windows cpolar 解包及正式 `maid-atelier` 0.1.7 下有内容轨迹的布局修复。不代表全部第三方皮肤或报告者设备已验收 |
400
407
  | `0.6.6` | `0.2.0-rc.2`、`0.2.1-alpha.2` 的打包附件接收与图片预览回归,覆盖多图、取消、迟到结果和旧请求;Android 系统选择器改进独立发布,不包含在 npm 更新中 |
408
+ | `0.6.8` | `0.2.1-alpha.3` 的打包移动页面、旧 WebView API 模拟、WebSocket 工作区读取、移动设置、模块管理、侧栏及输入栏回归;身份修复另有真实 HTTP/TLS 与旧凭据升级测试。本机官方 Desktop `0.2.0-rc.2` 已加载该版本插件,原配对保留;不代表手机 5G 或全部第三方插件组合已验收 |
401
409
 
402
410
  <details>
403
411
  <summary>历史版本验证记录</summary>
package/SECURITY.md CHANGED
@@ -27,6 +27,15 @@ The maintainer will acknowledge a complete report within seven days. Publication
27
27
  - The 0.4.6 existing-frps self-signed entry instead forwards raw TCP to the computer-side HTTPS gateway. Its QR link and bare App key carry a versioned `dsh2` CA-required marker, which Android 0.4.5 and earlier reject. During explicit remote pairing, the 0.4.6 app retrieves the gateway's public CA without sending a credential, checks its validity and SHA-256 fingerprint against the pairing key, and pins it to the exact Origin; HTTP 404, a missing, changed, or untrusted CA cannot downgrade this flow to platform trust. Re-pairing an existing pinned identity retains that CA requirement. The existing exact-Origin device-token restriction still applies: a CA fingerprint alone cannot renew a device credential. The CA is not installed in Android's system trust store. The 0.4.5 app lacks this remote CA-pinning path, and ordinary phone browsers will not trust the self-signed certificate.
28
28
  - Keep pairing closed except during a short local onboarding action.
29
29
  - Revoke a lost device immediately and rotate the device registry if credential theft is suspected.
30
+
31
+ ### Installation identity and device-state upgrades
32
+
33
+ - Automatically identified entries without a pairing CA use the random `installation-id` file in the active Mobile state directory for new pairings, not a hash of the state-file path. Explicit operator IDs and CA-bound LAN/self-signed FRP identities remain unchanged. The identifier is public, not an authentication secret. Copying the entire state directory also copies its identity and credentials; this fix does not distinguish cloned installations. Do not delete the identity file to troubleshoot a connection.
34
+ - Initial identity creation requires a filesystem that supports hard links within the Mobile state directory. A complete private candidate is published without replacing an existing identity, so concurrent starts cannot read a partially written identifier. Unsupported filesystems or invalid identity files fail explicitly; the plugin does not silently generate a replacement. Reading an existing valid identity does not require creating a hard link.
35
+ - Plugin 0.6.8 reads device-state versions 1 and 2 and writes version 2 on the next mutation. New records retain an optional `nativeInstanceId` binding, so authenticated native renewal and probe return the identity used for their pairing. Older unbound records keep the gateway's legacy identity during an ordinary upgrade with the same state path and gateway configuration; moving their state or changing their certificate/operator identity is not covered by this preservation. They are not reassigned from discovery metadata. The native response fields remain unchanged and the published Android App 0.6.3 needs no update for this fix.
36
+ - Stop the old Gateway normally before updating, then restart DSH. Do not run old and new plugins against the same state concurrently. Plugin 0.6.7 and earlier cannot read version 2; if downgrade may be necessary, stop DSH and back up the complete Mobile state directory before upgrading. There is no automatic rollback or data reset. Restoring a pre-upgrade backup is a separate operator action and can also restore credentials revoked since that backup: review and revoke those devices again before exposing the entry.
37
+ - Working pairings do not need to be recreated. A credential already overwritten in the App cannot be reconstructed by the plugin; pair each affected computer again after updating. A usable legacy row may remain beside a new row at the same Origin. Remove a redundant local row only after confirming the new one works; the upgrade does not automatically delete local rows or revoke their computer-side credentials.
38
+
30
39
  ### Remote components, diagnostics and cleanup
31
40
 
32
41
  - Do not expose the LAN gateway through router port forwarding. Funnel, cpolar, cloudflared, and FRP reach a separate loopback gateway through their selected remote path. The own reverse-proxy provider instead exposes a plugin-owned private HTTP origin restricted by its bind address and allowed source CIDRs; the operator's proxy must provide public HTTPS. Funnel, cpolar, cloudflared, Caddy, or the own proxy terminates public TLS in their respective modes; the 0.4.6 self-signed FRP entry terminates TLS on the computer. DSH pairing, device authentication, CSRF checks, and session revocation remain enforced by the plugin gateway.
@@ -0,0 +1,81 @@
1
+ # cpolar reserved subdomain
2
+
3
+ [中文指南](CPOLAR_SUBDOMAIN.md)
4
+
5
+ > Requires plugin **0.6.7 or later**; versions through 0.6.6 do not read these two settings. No Android App update is required.
6
+
7
+ cpolar assigns a temporary public address by default. Reserving a subdomain lets an account request a fixed address, reducing bookmark updates and re-pairing after tunnel restarts. A fixed address does not keep the tunnel permanently online or remove re-pairing requirements after credentials expire or a device is revoked.
8
+
9
+ The public entry still reaches the DSH Mobile Gateway with HTTPS, device pairing and authorization checks; it does not expose the ordinary DSH WebServer directly.
10
+
11
+ ## Prerequisites
12
+
13
+ 1. Check that your cpolar plan supports reserving a secondary subdomain. The [official tutorial](https://www.cpolar.com/blog/cpolar-quick-start-tutorial-raspberry-pi-series) uses Basic plans or above; your account dashboard is the authority for current eligibility, available regions and naming rules.
14
+ 2. Reserve a name under **Reserved → Reserve a secondary subdomain** in the [cpolar dashboard](https://dashboard.cpolar.com), and record the selected region.
15
+ 3. Install the component and save the Authtoken under **Mobile access → Remote → cpolar** in DSH.
16
+
17
+ The region must match the reservation. The official command example uses `cn_vip`, but do not copy it for a reservation in another region; confirm other identifiers against cpolar's current instructions. This guide does not maintain a fixed region or domain-suffix mapping.
18
+
19
+ ## Configuration
20
+
21
+ > The panel has no subdomain or region fields yet. Edit the current DSH profile's `cordis.patch.yml` after making a backup; do not edit generated `cordis.yml` or the plugin-managed `cpolar.yml`.
22
+
23
+ Find the current profile directory, for example `$DSH_HOME/profiles/<profile>/cordis.patch.yml`. Update the existing `mobile-access` configuration override. If none exists, add the override below to a profile that already loads the DSH Mobile bundle. **Do not create a second `mobile-access` instance or copy the bundle's `insert` list again.**
24
+
25
+ The DSH loader replaces an entry's entire `config`, rather than merging individual keys. Do not paste an override containing only the subdomain and region. This example includes every configuration field from this repository's standard bundle, followed by the two new settings; **it is only suitable for a standard installation without custom configuration for this entry**:
26
+
27
+ ```yaml
28
+ - id: mobile-access
29
+ name: dsh-mobile
30
+ config:
31
+ setupFile: !!js dshHomePath('mobile-access/setup.json')
32
+ stateFile: !!js dshHomePath('mobile-access/devices.json')
33
+ controlFile: !!js dshHomePath('mobile-access/control.json')
34
+ customCssFile: !!js dshHomePath('mobile-access/mobile.css')
35
+ customScriptFile: !!js dshHomePath('mobile-access/mobile.js')
36
+ initiallyEnabled: false
37
+ listenHost: 127.0.0.1
38
+ listenPort: 3443
39
+ allowedCidrs: [127.0.0.0/8]
40
+ tls:
41
+ mode: disabled
42
+ cpolarSubdomain: your-reserved-name
43
+ cpolarRegion: cn_vip
44
+ ```
45
+
46
+ If you already customize paths, listeners, TLS or other settings, **keep your current complete `config` and add only these two fields inside it**. Replacing it with the example can change data locations or access settings. Do not add the Authtoken here; save it through the panel as before.
47
+
48
+ | Field | Value |
49
+ | --- | --- |
50
+ | `cpolarSubdomain` | The reserved name itself, not a full domain, HTTPS address or path. Omitted, empty or whitespace-only values do not request a fixed name. |
51
+ | `cpolarRegion` | The region identifier matching your reservation; `cn_vip` above is only an official example. Omitted, empty or whitespace-only values do not send a region argument, leaving routing to cpolar; specify the matching region for a fixed reservation. |
52
+
53
+ Leading and trailing whitespace is removed. The plugin only bounds the requested name's syntax: it starts with a letter or digit, contains letters, digits, `.`, `_`, `-`, and is at most 63 characters long. This is not a DNS-label specification or a guarantee of server acceptance. The account, region and cpolar's actual rules determine whether the reservation is valid. The [official subdomain instructions](https://www.cpolar.com/docs#configure-secondary-subdomain) and tutorial describe the `-subdomain` and `-region` arguments.
54
+
55
+ After checking that no tasks are running, quit DSH completely and reopen it, then connect under **Mobile access → Remote → cpolar**. Use the actual HTTPS address shown by the panel; do not construct a domain suffix yourself.
56
+
57
+ ## Verification and pairing
58
+
59
+ 1. Compare the public hostname displayed by the panel with your account's reservation.
60
+ 2. From the external network used by the phone, open `https://<hostname-shown-by-the-panel>/mobile-access/health`, check the HTTPS certificate and confirm a `{"ok":true}` response. This is a basic connectivity check; an HTTP `401`, `301`, or an accessible webpage alone does not identify your DSH gateway.
61
+ 3. When the target computer needs confirmation, compare the `instanceId` returned by that address's `/mobile-access/discovery` with the local gateway's value. Do not publish full discovery responses, pairing codes or credentials.
62
+ 4. Choose **Remote** in the Android App and connect using the remote pairing QR code generated by the panel. Check that workspaces and conversations load and real-time connections work; the panel's connection diagnostics can also help. No model request is needed to check connectivity.
63
+
64
+ Existing pairings are bound to an exact HTTPS Origin. Switching from a temporary address to a fixed address requires pairing once more. Afterwards the record remains usable while the address stays unchanged and authorization remains valid. A fixed domain does not prevent Token expiry, device revocation, certificate problems or provider outages.
65
+
66
+ ## Troubleshooting
67
+
68
+ | Symptom | Checks and action |
69
+ | --- | --- |
70
+ | A temporary address is still displayed | Confirm that plugin 0.6.7 or later is running, the fields are inside the existing `mobile-access` entry's complete `config`, and DSH has fully restarted. Then check the account reservation and region; local configuration alone is not success. |
71
+ | The plugin reports `cpolar subdomain is invalid` | Check the request syntax and 63-character limit above, using only the reserved name. Passing local syntax checks still does not ensure cpolar accepts it. |
72
+ | The plugin reports `cpolar region is invalid` | The format starts with a lowercase letter, followed only by lowercase letters, digits or underscores, up to 32 characters. Also confirm the identifier is valid for the account reservation. |
73
+ | cpolar rejects the name or fails to start | Check the current plan, account, reserved name and region; inspect the error and follow cpolar's current instructions. The plugin does not treat the requested value as a successfully returned public address. |
74
+ | Health responds but workspaces do not load | Check pairing authorization and the actual WebSocket connection using connection diagnostics; a successful health request does not establish a working session. |
75
+ | Data or listeners changed after editing | Check for omitted fields from the original complete `config`; restore the original paths and access settings from your backup. Do not delete pairing files. |
76
+
77
+ ## Security boundaries
78
+
79
+ - These settings only append `-subdomain` and `-region` arguments to `cpolar http`; gateway pairing, TLS and device authorization are unchanged.
80
+ - The plugin still uses only the public address actually reported by cpolar and validated by the plugin; the entered name does not become a trusted Origin on its own.
81
+ - The Authtoken retains its existing private storage. The reserved name appears in the public domain and is not secret, but do not publish it together with Tokens, Cookies or pairing QR codes.
@@ -0,0 +1,81 @@
1
+ # cpolar 固定子域名
2
+
3
+ [English guide](CPOLAR_SUBDOMAIN.en.md)
4
+
5
+ > 需要插件 **0.6.7 或更新版本**;0.6.6 及之前版本尚不读取这两个配置项。此功能不要求更新 Android App。
6
+
7
+ cpolar 默认分配临时公网地址。账号预留子域名后,可请求使用固定地址,减少重启隧道后更新书签或重新配对的次数。固定地址不意味着隧道永远在线,也不取消设备凭据过期或撤销后的重新配对要求。
8
+
9
+ 公网入口仍由 DSH Mobile Gateway 处理,沿用 HTTPS、设备配对和授权检查;不是直接开放 DSH 的普通 WebServer。
10
+
11
+ ## 前置条件
12
+
13
+ 1. 确认 cpolar 套餐支持保留二级子域名。[官方教程](https://www.cpolar.com/blog/cpolar-quick-start-tutorial-raspberry-pi-series)以基础套餐及以上为例;当前资格、可用地区及命名规则以你的账号控制台为准。
14
+ 2. 在 [cpolar 控制台](https://dashboard.cpolar.com)的 **预留 → 保留二级子域名** 中保留名字,记录对应地区。
15
+ 3. 在 DSH **移动访问 → 远程 → cpolar** 中安装组件并保存 Authtoken。
16
+
17
+ 地区必须与预留记录一致。官方命令示例使用 `cn_vip`,但不要将它照抄到其他地区的预留记录;其他地区的配置值请按 cpolar 当前说明确认。本指南不提供固定地区或域名后缀对照表。
18
+
19
+ ## 配置
20
+
21
+ > 面板暂时没有子域名和地区输入框,需要编辑当前 DSH profile 的 `cordis.patch.yml`。先备份;不要改生成的 `cordis.yml` 或插件管理的 `cpolar.yml`。
22
+
23
+ 找到当前 profile 目录,例如 `$DSH_HOME/profiles/<profile>/cordis.patch.yml`。修改已有的 `mobile-access` 配置覆盖条目;没有时,可在已加载 DSH Mobile bundle 的 profile 中添加下面的覆盖。**不要新增第二个 `mobile-access` 实例,也不要重新复制 bundle 的 `insert` 列表。**
24
+
25
+ DSH 加载器会整体替换条目的 `config`,不是逐键合并。因此不能只粘贴子域名和地区两个字段。下面展示本仓库标准 bundle 的全部配置,再追加两个设置;**仅适用于尚未自定义该条目的标准安装**:
26
+
27
+ ```yaml
28
+ - id: mobile-access
29
+ name: dsh-mobile
30
+ config:
31
+ setupFile: !!js dshHomePath('mobile-access/setup.json')
32
+ stateFile: !!js dshHomePath('mobile-access/devices.json')
33
+ controlFile: !!js dshHomePath('mobile-access/control.json')
34
+ customCssFile: !!js dshHomePath('mobile-access/mobile.css')
35
+ customScriptFile: !!js dshHomePath('mobile-access/mobile.js')
36
+ initiallyEnabled: false
37
+ listenHost: 127.0.0.1
38
+ listenPort: 3443
39
+ allowedCidrs: [127.0.0.0/8]
40
+ tls:
41
+ mode: disabled
42
+ cpolarSubdomain: your-reserved-name
43
+ cpolarRegion: cn_vip
44
+ ```
45
+
46
+ 已有自定义路径、监听、TLS 或其他设置时,**保留你当前的完整 `config`,只在其中添加这两个字段**;不要用示例覆盖它,否则可能改变数据位置或访问设置。无需在配置中填写 Authtoken,它仍通过面板保存。
47
+
48
+ | 字段 | 填写内容 |
49
+ | --- | --- |
50
+ | `cpolarSubdomain` | 控制台预留的名字本身,不是完整域名、HTTPS 地址或路径。省略、空字符串或纯空白表示不请求固定名字。 |
51
+ | `cpolarRegion` | 与预留记录匹配的地区标识;上例 `cn_vip` 只是官方示例。省略、空字符串或纯空白时不传地区参数,由 cpolar 决定线路;固定名字建议填写匹配地区。 |
52
+
53
+ 配置值会去除首尾空白。插件的名字检查仅限制请求格式:以字母或数字开头,只含字母、数字、`.`、`_`、`-`,长度不超过 63 字符;这不是 DNS 标签规范,也不代表 cpolar 服务端会接受。预留是否有效仍取决于账号、地区和 cpolar 的实际规则。[官方子域名配置说明](https://www.cpolar.com/docs#configure-secondary-subdomain)与教程说明了 `-subdomain`、`-region` 参数。
54
+
55
+ 确认没有正在运行的任务后,完整退出并重开 DSH,再在 **移动访问 → 远程 → cpolar** 中连接。连接后使用面板实际显示的 HTTPS 地址,不要自行拼接域名后缀。
56
+
57
+ ## 验证与配对
58
+
59
+ 1. 核对面板显示的公网主机名与账号预留记录一致。
60
+ 2. 从手机实际使用的外网打开 `https://<面板显示的主机名>/mobile-access/health`,检查 HTTPS 证书并确认响应为 `{"ok":true}`。这是基础连通性检查;单独的 HTTP `401`、`301` 或“网页能打开”不能证明请求到达你的 DSH。
61
+ 3. 若需确认目标电脑,比较该地址 `/mobile-access/discovery` 返回的 `instanceId` 与本机网关的值;不要公开完整 discovery 响应、配对码或凭据。
62
+ 4. 在 Android App 选择 **远程访问**,使用面板生成的远程配对二维码连接,确认工作区和会话可以读取、实时连接正常;也可查看面板的连接诊断。不需要发送模型请求来验证连通性。
63
+
64
+ 已有配对记录绑定精确 HTTPS Origin。由临时地址换成固定地址时,需要重新配对一次;以后地址保持不变且授权仍有效时可继续使用原记录。固定域名不会阻止 Token 过期、设备撤销、证书问题或提供方故障。
65
+
66
+ ## 常见问题
67
+
68
+ | 现象 | 检查与处理 |
69
+ | --- | --- |
70
+ | 仍显示临时地址 | 确认插件为 0.6.7 或更新版本、字段位于已有 `mobile-access` 的完整 `config` 中,并已完整重启。再核对账号预留和地区,不要仅凭本地字段存在判断成功。 |
71
+ | 插件报 `cpolar subdomain is invalid` | 检查前述请求格式和 63 字符上限,只填预留名字;符合本地格式仍可能被 cpolar 拒绝。 |
72
+ | 插件报 `cpolar region is invalid` | 地区格式为小写字母开头,后续仅小写字母、数字或下划线,最多 32 字符;再按账号预留记录确认它确实有效。 |
73
+ | cpolar 拒绝固定名字或无法启动 | 核对当前套餐、账号、预留名字和地区;查看错误信息并按 cpolar 当前说明处理。插件不会把请求值当成成功返回的公网地址。 |
74
+ | 健康检查正常但工作区加载失败 | 继续检查配对授权和实际 WebSocket 连接,使用连接诊断;健康接口成功不等于完整会话可用。 |
75
+ | 改配置后数据或监听异常 | 检查是否遗漏了原有完整 `config`,从备份恢复原路径与访问设置;不要删除配对文件。 |
76
+
77
+ ## 安全边界
78
+
79
+ - 这两个设置只追加 `cpolar http` 的 `-subdomain` 与 `-region` 参数,不改变网关配对、TLS 或设备授权逻辑。
80
+ - 插件仍只使用 cpolar 实际报告并校验通过的公网地址,不会把填写的名字直接当成可信 Origin。
81
+ - Authtoken 保持原有私有存储方式;预留名字会出现在公网域名中,不是秘密,但不要连同 Token、Cookie 或配对二维码公开。
package/docs/README.md CHANGED
@@ -8,6 +8,7 @@
8
8
  | --- | --- | --- |
9
9
  | 使用 Android App、了解返回键、权限与升级 | [App 手册](../apps/mobile/README.zh-CN.md) | [Android app](../apps/mobile/README.md) |
10
10
  | 使用固定 Cloudflare 域名,而非临时随机地址 | [命名隧道](CLOUDFLARE_TUNNEL.md) | [Named tunnel](CLOUDFLARE_TUNNEL.en.md) |
11
+ | 请求 cpolar 账号已预留的固定子域名(0.6.7 起) | [固定子域名](CPOLAR_SUBDOMAIN.md) | [Reserved subdomain](CPOLAR_SUBDOMAIN.en.md) |
11
12
  | 在已有 VPS 上新部署 FRP 与 HTTPS 入口 | [自建 FRP](SELF_HOSTED_FRP.md) | [Self-hosted FRP](SELF_HOSTED_FRP.en.md) |
12
13
  | 复用已经运行的 frps,不自动修改服务器 | [接入既有 frps](ATTACH_EXISTING_FRPS.md) | [Existing frps](ATTACH_EXISTING_FRPS.en.md) |
13
14
  | 复用 Lucky、Nginx 或 Caddy 的公开 HTTPS 入口 | [自有反向代理](SELF_HOSTED_ORIGIN.md) | [Own reverse proxy](SELF_HOSTED_ORIGIN.en.md) |
@@ -14,7 +14,7 @@ If saving reports a dependency conflict, retain the required module or also dese
14
14
 
15
15
  - Identify the running plugin, App and skin versions; plugin and App versions need not match.
16
16
  - Omit the skin only on this device, reopen manually and compare the conversation, composer and sidebar. Recovery points to styles or mounting, not necessarily a network or pairing failure.
17
- - First compare the normal computer layout. Developers can also open `/?frontend=stock` on the authenticated mobile Origin for layout diagnosis. Gateway authentication and HTTPS checks remain, but mobile enhancements and module selection are bypassed; some API operations may be rejected. It is not a replacement for the normal mobile entry.
17
+ - First compare the normal computer layout. Developers can also open `/?frontend=stock` on the authenticated mobile Origin to diagnose boot and layout behavior. Gateway authentication and HTTPS checks remain; this entry skips dedicated mobile boot rewriting and module selection, but installed client adaptation and authenticated customizations may still apply. It is not a plugin-free control; some API operations may be rejected, so it does not replace normal mobile access.
18
18
  - When stock has a background but mobile does not, inspect the skin's mounting container and fallback for other layouts. WebSocket approval, APK reinstallation or making every container transparent cannot guarantee a fix.
19
19
  - A see-through sidebar, unreadable text shadows and an empty trace need separate diagnosis, not a single missing-background explanation. For an empty trace, inspect the first client exception, actual layout dimensions and whether its module loaded. A static screenshot does not distinguish rendering failure, occlusion and connection failure.
20
20
 
@@ -14,7 +14,7 @@ DSH Mobile 在已认证的移动页面中使用专用根布局,继续渲染 DS
14
14
 
15
15
  - 先核对正在运行的插件、App 和皮肤版本;插件与 App 版本不必相同。
16
16
  - 只在本设备不加载皮肤,手动重新打开后比较会话、输入栏和侧栏。恢复正常说明需要检查双方样式与挂载位置,不表示网络或配对失效。
17
- - 先与电脑上的原生布局对照。开发者还可在已认证移动 Origin 打开 `/?frontend=stock` 作布局诊断;它保留 Gateway 认证与 HTTPS 检查,但绕过移动增强和模块选择,部分 API 操作可能被拒绝,不能代替正常移动入口。
17
+ - 先与电脑上的原生布局对照。开发者还可在已认证移动 Origin 打开 `/?frontend=stock` 作启动与布局诊断;它保留 Gateway 认证与 HTTPS 检查,跳过专用移动启动改写和模块选择,但仍可能加载客户端移动适配及已认证定制,并非不含插件的对照页。部分 API 操作可能被拒绝,不能代替正常移动入口。
18
18
  - 若原生布局有背景而移动布局没有,检查皮肤背景的挂载容器及其对非原生布局的回退逻辑;单纯放行 WebSocket、重装 APK 或把全部容器设为透明不能保证修复。
19
19
  - 侧栏透底、文字阴影难读和轨迹空白应分别排查,不能都归为“少了一张背景图”。轨迹空白时还需检查首个客户端异常、实际布局尺寸和是否加载了相应模块;仅从静态截图不能判断是渲染异常、遮挡还是连接问题。
20
20
 
package/lib/cli.js CHANGED
@@ -603,6 +603,8 @@ Object.freeze({
603
603
  assetBytes: 33554432,
604
604
  assetDepth: 8
605
605
  });
606
+ //#endregion
607
+ //#region src/extensions.ts
606
608
  /** A controlled business failure returned by an extension action or route. */
607
609
  var MobileExtensionError = class extends Error {
608
610
  code;