dsh-plugin-dshm 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/LICENSE +21 -0
- package/README.md +228 -2
- package/README.zh-CN.md +190 -0
- package/cordis.patch.yml +7 -0
- package/lib/auth/signature.d.ts +4 -0
- package/lib/auth/signature.js +24 -0
- package/lib/cli/index.d.ts +4 -0
- package/lib/cli/index.js +41 -0
- package/lib/client.js +419 -0
- package/lib/config.d.ts +10 -0
- package/lib/config.js +27 -0
- package/lib/discovery/advertiser.d.ts +45 -0
- package/lib/discovery/advertiser.js +141 -0
- package/lib/discovery/interfaces.d.ts +5 -0
- package/lib/discovery/interfaces.js +24 -0
- package/lib/errors.d.ts +5 -0
- package/lib/errors.js +10 -0
- package/lib/host/local.d.ts +5 -0
- package/lib/host/local.js +122 -0
- package/lib/host/tailscale.d.ts +43 -0
- package/lib/host/tailscale.js +137 -0
- package/lib/host/types.d.ts +40 -0
- package/lib/host/types.js +1 -0
- package/lib/index.d.ts +30 -0
- package/lib/index.js +98 -0
- package/lib/methods/index.d.ts +9 -0
- package/lib/methods/index.js +206 -0
- package/lib/pairing/state.d.ts +26 -0
- package/lib/pairing/state.js +89 -0
- package/lib/pairing/window.d.ts +18 -0
- package/lib/pairing/window.js +57 -0
- package/lib/projection/client.d.mts +2 -0
- package/lib/projection/client.mjs +11 -0
- package/lib/projection/files.d.ts +33 -0
- package/lib/projection/files.js +278 -0
- package/lib/projection/fold-recording.d.mts +50 -0
- package/lib/projection/fold-recording.mjs +440 -0
- package/lib/projection/host.d.ts +6 -0
- package/lib/projection/host.js +86 -0
- package/lib/projection/ids.d.mts +1 -0
- package/lib/projection/ids.mjs +1 -0
- package/lib/projection/index.d.ts +2 -0
- package/lib/projection/index.js +2 -0
- package/lib/projection/interactions.d.ts +10 -0
- package/lib/projection/interactions.js +73 -0
- package/lib/projection/native.d.ts +114 -0
- package/lib/projection/native.js +903 -0
- package/lib/protocol/THIRD_PARTY_LICENSES.txt +135 -0
- package/lib/protocol/dmp.d.ts +402 -0
- package/lib/protocol/dmp.js +1 -0
- package/lib/protocol/schema/dmp-v1/common.schema.json +88 -0
- package/lib/protocol/schema/dmp-v1/events.schema.json +107 -0
- package/lib/protocol/schema/dmp-v1/frames.schema.json +280 -0
- package/lib/protocol/schema/dmp-v1/methods.schema.json +584 -0
- package/lib/protocol/schema/dmp-v1/models.schema.json +674 -0
- package/lib/protocol/scripts/contract.mjs +8106 -0
- package/lib/push/controller.d.ts +64 -0
- package/lib/push/controller.js +290 -0
- package/lib/push/observer.d.ts +51 -0
- package/lib/push/observer.js +266 -0
- package/lib/push/payload.d.ts +15 -0
- package/lib/push/payload.js +18 -0
- package/lib/push/store.d.ts +17 -0
- package/lib/push/store.js +75 -0
- package/lib/server/index.d.ts +30 -0
- package/lib/server/index.js +500 -0
- package/lib/server/rate-limit.d.ts +7 -0
- package/lib/server/rate-limit.js +19 -0
- package/lib/server/uploads.d.ts +21 -0
- package/lib/server/uploads.js +74 -0
- package/lib/types.d.ts +92 -0
- package/lib/types.js +1 -0
- package/lib/ui/card.d.mts +3 -0
- package/lib/ui/card.mjs +59 -0
- package/lib/ui/copy.d.mts +146 -0
- package/lib/ui/copy.mjs +106 -0
- package/lib/ui/remote-setup.d.mts +81 -0
- package/lib/ui/remote-setup.mjs +75 -0
- package/package.json +67 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 — 2026-10-28
|
|
4
|
+
|
|
5
|
+
Initial DSHM bridge release for DeepSeek Harness 0.2.1-rc.3.
|
|
6
|
+
|
|
7
|
+
- Pair an iPhone or iPad using a short-lived code and pinned TLS; authenticate
|
|
8
|
+
paired devices and revoke access from the DSH settings card.
|
|
9
|
+
- Follow sessions, send prompts, answer approvals/questions and transfer files
|
|
10
|
+
over a reachable private network or the user's own VPN.
|
|
11
|
+
- English and Simplified Chinese settings card with optional Tailscale setup
|
|
12
|
+
guidance under “Not on the same Wi-Fi / 不在同一 Wi-Fi”.
|
|
13
|
+
- Optional encrypted push sender; proxy deployment and real-device notification
|
|
14
|
+
delivery are separate from this package's local verification.
|
|
15
|
+
- MIT license and a separate plugin-only public source repository. The iOS app,
|
|
16
|
+
private development history and push-proxy source are not part of this release.
|
|
17
|
+
|
|
18
|
+
Fresh-install and remote-phone acceptance of the new Tailscale setup helper
|
|
19
|
+
remain pending. Earlier Windows LAN/remote tests used the previous package.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DSHM contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,229 @@
|
|
|
1
|
-
#
|
|
1
|
+
# DSHM bridge
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[简体中文](README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
Control DeepSeek Harness sessions on your computer from the DSHM app on your
|
|
6
|
+
iPhone or iPad. The agent keeps running on your computer; the bridge connects
|
|
7
|
+
your paired device over your local network or your own VPN.
|
|
8
|
+
|
|
9
|
+
## Requirements and compatibility
|
|
10
|
+
|
|
11
|
+
- DeepSeek Harness **0.2.1-rc.3**, the exact currently supported `engines.dsh`
|
|
12
|
+
value. DSH is a Developer Preview; a newer version is not automatically
|
|
13
|
+
compatible.
|
|
14
|
+
- A running DSH desktop app or `dsh web` on your computer, and a compatible DSHM
|
|
15
|
+
iPhone/iPad build. This npm package does not install the iOS app.
|
|
16
|
+
- Node 24 or later in the DSH runtime, and `openssl` on its PATH for the initial
|
|
17
|
+
local TLS certificate.
|
|
18
|
+
- Both devices on a network that permits direct communication, or on your own
|
|
19
|
+
connected VPN such as Tailscale.
|
|
20
|
+
|
|
21
|
+
The bridge has been exercised with DSH 0.2.1-rc.3 on macOS, including the desktop
|
|
22
|
+
app and isolated `dsh web`. Windows is an intended platform, but its native
|
|
23
|
+
runtime/firewall checklist is still pending; do not treat the macOS tests as
|
|
24
|
+
Windows verification. Physical-phone network acceptance is also separate from
|
|
25
|
+
the local test-client and Simulator results. Mainland China is outside the v1
|
|
26
|
+
release scope; mainland network reachability is not claimed.
|
|
27
|
+
|
|
28
|
+
## Install in DSH
|
|
29
|
+
|
|
30
|
+
1. Open the **Plugins** page in the DSH instance you want to control.
|
|
31
|
+
2. Install this package spec using the page's package installation control:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
dsh-plugin-dshm
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
3. Let DSH's plugin manager install the bundle and dependencies. Restart DSH
|
|
38
|
+
when requested, then open **Settings → DSHM**.
|
|
39
|
+
|
|
40
|
+
Use DSH's plugin manager rather than editing its profile files or copying files
|
|
41
|
+
into the installed application. The plugin is installed into the selected DSH
|
|
42
|
+
profile; installing it into one profile does not enable every other profile.
|
|
43
|
+
|
|
44
|
+
DSH 0.2.1 installs packages by name from npm; there is no central DSH plugin
|
|
45
|
+
market. No DSHM custom plugin index is published for this release.
|
|
46
|
+
|
|
47
|
+
## Pair your device
|
|
48
|
+
|
|
49
|
+
### Guided remote setup
|
|
50
|
+
|
|
51
|
+
Phone not on the same Wi-Fi as this computer? Use Tailscale. On the same Wi-Fi,
|
|
52
|
+
nothing else is needed. Open **Settings → DSHM → Not on the same Wi-Fi**.
|
|
53
|
+
The optional helper checks the official Tailscale app on Windows/macOS, links
|
|
54
|
+
to its official installer instructions, and can open the installed app on the
|
|
55
|
+
DSH host. Complete installation, system approvals and browser sign-in yourself.
|
|
56
|
+
If viewing DSH from another computer, install Tailscale on the **DSH host**.
|
|
57
|
+
The plugin does not embed a VPN, install software automatically, or change
|
|
58
|
+
Tailscale accounts, DNS, routes, exit nodes, firewall or proxy settings.
|
|
59
|
+
|
|
60
|
+
Install Tailscale on your iPhone/iPad, sign in to the same personal account,
|
|
61
|
+
and connect both ends. For organization accounts, both devices must belong to
|
|
62
|
+
the same permitted tailnet; account sign-in does not override access policy.
|
|
63
|
+
Then select **Pair for remote access** and scan the fresh QR in DSHM. An older
|
|
64
|
+
LAN-only pairing does not automatically acquire the new VPN address: forget
|
|
65
|
+
the old computer in DSHM, revoke its old device entry on the host, and pair again.
|
|
66
|
+
An active earlier QR is replaced when you explicitly create the fresh one.
|
|
67
|
+
|
|
68
|
+
The card distinguishes PC readiness from **Phone connected over Tailscale**.
|
|
69
|
+
Test with your phone on cellular or a different Wi-Fi.
|
|
70
|
+
**Pair a device** remains available for ordinary LAN use without Tailscale.
|
|
71
|
+
Missing software, canceled installation, sign-out and unavailable status checks
|
|
72
|
+
do not disable local pairing. Removing this plugin leaves Tailscale installed.
|
|
73
|
+
Fresh-install and remote-phone acceptance of this helper remain pending.
|
|
74
|
+
Earlier Windows LAN/remote tests used the previous package.
|
|
75
|
+
|
|
76
|
+
The helper reads local Tailscale state only while setup is open or when you
|
|
77
|
+
request remote pairing. It returns connection state and local VPN addresses,
|
|
78
|
+
not account identities, login links or peer inventories. Tailscale is a separate
|
|
79
|
+
service with its own account and privacy terms; DSHM's pinned TLS remains in use
|
|
80
|
+
over that VPN.
|
|
81
|
+
|
|
82
|
+
### Local pairing
|
|
83
|
+
|
|
84
|
+
1. Keep DSH running. On the computer, open **Settings → DSHM → Pair a device**.
|
|
85
|
+
2. In DSHM on your iPhone or iPad, add a computer and scan the displayed QR code.
|
|
86
|
+
3. Allow local-network access when prompted. The computer's DSHM card should
|
|
87
|
+
show your device as **Connected**.
|
|
88
|
+
|
|
89
|
+
The QR code is private, single use and valid for five minutes. Do not share it
|
|
90
|
+
or include it in screenshots or support reports. **Cancel pairing** closes the
|
|
91
|
+
window; if it expires, start a new one. Pair only devices you trust: paired
|
|
92
|
+
devices can view sessions and files, send prompts and answer tool approvals.
|
|
93
|
+
|
|
94
|
+
To disconnect a lost or unwanted device, use **Settings → DSHM → Revoke**, then
|
|
95
|
+
confirm **Revoke device**. This closes its active connection and prevents that
|
|
96
|
+
pairing from reconnecting. Pair again if you later want to restore access.
|
|
97
|
+
|
|
98
|
+
## Network setup
|
|
99
|
+
|
|
100
|
+
- **macOS:** allow **DeepSeek Harness** in **System Settings → Privacy & Security
|
|
101
|
+
→ Local Network**. If you run `dsh web` in Terminal or another terminal app,
|
|
102
|
+
allow that app too. DSHM on iOS also needs Local Network permission.
|
|
103
|
+
- **Windows:** if Windows Firewall asks about the DSH host process, allow it on
|
|
104
|
+
your trusted **Private networks**. Keep **Public networks** disabled. The
|
|
105
|
+
bridge does not change firewall rules for you; Windows runtime verification
|
|
106
|
+
remains pending.
|
|
107
|
+
- **Wi-Fi:** start with the same trusted home/work Wi-Fi. Guest networks,
|
|
108
|
+
hotspots and router client isolation may prevent devices from reaching each
|
|
109
|
+
other even when both have internet access.
|
|
110
|
+
- **Proxies and VPNs:** enable **bypass LAN/local networks** on both devices, or
|
|
111
|
+
temporarily turn the interfering proxy off to check the route. Keep LAN and
|
|
112
|
+
the chosen VPN's device addresses reachable; a rule that routes all traffic
|
|
113
|
+
through a proxy can prevent pairing.
|
|
114
|
+
- **Not on the same Wi-Fi:** connect both devices to the same Tailscale network (or
|
|
115
|
+
another VPN you control) and permit traffic between them. Keep the computer
|
|
116
|
+
awake and DSH running. DSHM does not provide a cloud relay for session traffic. Bonjour may
|
|
117
|
+
not cross a VPN; pair while both devices can reach an address included by the
|
|
118
|
+
computer.
|
|
119
|
+
|
|
120
|
+
The bridge normally listens on TCP **47390** on private/LAN and Tailscale
|
|
121
|
+
addresses. It uses a separate listener from DSH's Web UI. Do not expose that
|
|
122
|
+
port by router port forwarding or change DSH's Web server to a public bind.
|
|
123
|
+
Bonjour discovery uses the local network. If discovery sees your computer but
|
|
124
|
+
connection fails, check permissions, VPN/proxy bypass and client isolation first.
|
|
125
|
+
|
|
126
|
+
## What is sent, and where
|
|
127
|
+
|
|
128
|
+
The bridge sends session messages, tool results, approvals, selected files and
|
|
129
|
+
declared deliverables to your authenticated, paired device over pinned TLS.
|
|
130
|
+
Prompts, answers and attachments from that device go back to DSH on your
|
|
131
|
+
computer. The bridge runs no cloud agent and has no analytics service or relay
|
|
132
|
+
for session traffic. It does not read or forward DSH's provider-credential store.
|
|
133
|
+
DSH itself still contacts the model providers and tools you configured, under
|
|
134
|
+
their own settings.
|
|
135
|
+
|
|
136
|
+
On the LAN, Bonjour announces the bridge's host identity/version and private
|
|
137
|
+
addresses for discovery. Local bridge identity and pairing records stay under
|
|
138
|
+
`$DSH_HOME/dshm/` (`~/.dsh/dshm/` with the default DSH home); private files should
|
|
139
|
+
never be pasted into issues. Installing a package or using a remote plugin
|
|
140
|
+
index makes DSH contact the package registry/index host.
|
|
141
|
+
|
|
142
|
+
**Optional push notifications use a separate proxy and Apple Push Notification
|
|
143
|
+
service (APNs).** Without a configured `pushProxyUrl`, the bridge makes no push
|
|
144
|
+
network requests and does not advertise push support. Configuring a URL enables
|
|
145
|
+
periodic health checks; push support is advertised only while the proxy is
|
|
146
|
+
reachable and the bridge's session observer is working. This package includes the bridge sender; the proxy and app are separate. iOS push registration,
|
|
147
|
+
the Notification Service Extension and real locked-phone delivery remain
|
|
148
|
+
separate work; they have not been verified by the local backend tests.
|
|
149
|
+
|
|
150
|
+
For push registration, the app sends its APNs device token and sandbox/production
|
|
151
|
+
environment to the selected HTTPS proxy. The proxy stores that routing mapping
|
|
152
|
+
and encrypts its authentication secret under a separate wrapping key. The app
|
|
153
|
+
shares the returned registration and a separate notification-content key with
|
|
154
|
+
the paired bridge over DMP. The bridge stores these keys and preferences in its
|
|
155
|
+
private `$DSH_HOME/dshm/push.json` file (mode 0600). The APNs provider key stays
|
|
156
|
+
only in the proxy's secret configuration; it is never supplied to the bridge.
|
|
157
|
+
|
|
158
|
+
When notifications are configured and registered, the bridge sends the proxy
|
|
159
|
+
an encrypted session title and short event summary, plus an opaque push ID,
|
|
160
|
+
event category, grouping ID and request signature. The proxy forwards the
|
|
161
|
+
ciphertext and a generic fallback alert to APNs. The proxy and APNs do not
|
|
162
|
+
receive the notification-content key or decrypted title/summary; routing
|
|
163
|
+
metadata, timing and payload size remain visible, and the proxy receives the
|
|
164
|
+
client IP at the network layer. The application logs counters only and stores
|
|
165
|
+
hashed IP quota buckets. Push does not upload files or full transcripts, and
|
|
166
|
+
an authenticated live connection suppresses sends to that device.
|
|
167
|
+
|
|
168
|
+
Unregistering notifications or revoking a device removes its local push
|
|
169
|
+
registration before a best-effort request to delete the proxy mapping. If the
|
|
170
|
+
proxy is unreachable, remote deletion is not confirmed; uninstalling the
|
|
171
|
+
package alone does not delete a remote mapping. Alerts already accepted by
|
|
172
|
+
APNs cannot be recalled. Terminal output remains read-only; the bridge does
|
|
173
|
+
not provide an interactive remote terminal.
|
|
174
|
+
|
|
175
|
+
## Remove the bridge
|
|
176
|
+
|
|
177
|
+
1. In **Settings → DSHM**, revoke devices you no longer want to authorize.
|
|
178
|
+
2. Open **Plugins**, find `dsh-plugin-dshm`, and remove it from the active
|
|
179
|
+
profile through DSH's plugin manager. Repeat for any other profile where you
|
|
180
|
+
installed it, including an optional `dshm` CLI profile.
|
|
181
|
+
3. Restart the affected DSH host when requested. The DSHM settings card and its
|
|
182
|
+
listener should be gone from that host.
|
|
183
|
+
|
|
184
|
+
Uninstalling the package is separate from deleting its private identity and
|
|
185
|
+
pairing state. Preserve `$DSH_HOME/dshm/` if you intend to reinstall. If you
|
|
186
|
+
deliberately choose a full reset, stop every DSH host using that home first and
|
|
187
|
+
remove only the bridge's `dshm` state directory; existing devices will need to
|
|
188
|
+
forget the old host and pair again. Do not delete the whole DSH home or its
|
|
189
|
+
credentials/session directories. Uninstall does not remove your DSH sessions.
|
|
190
|
+
|
|
191
|
+
## New DSH release checklist (maintainers)
|
|
192
|
+
|
|
193
|
+
1. Keep `engines.dsh` at the currently verified version while testing. Review
|
|
194
|
+
upstream DSH changes, especially the projection APIs and bundle loader.
|
|
195
|
+
2. Install the candidate DSH runtime through its normal distribution and run
|
|
196
|
+
`pnpm -C bridge test:integration` against it in the isolated `.dsh-test` home.
|
|
197
|
+
Review the explicit runtime version guard in `bridge/src/projection/native.ts`
|
|
198
|
+
as part of the compatibility change; changing package metadata alone does
|
|
199
|
+
not enable a new runtime. Adapt the test carrier path if needed; do not
|
|
200
|
+
bypass a failure or test against the old runtime while claiming the new one. Record the
|
|
201
|
+
actual DSH version and results. Complete the Windows checklist before
|
|
202
|
+
claiming a newly supported Windows combination.
|
|
203
|
+
3. Run `pnpm -C bridge test`, `pnpm -C protocol validate` and
|
|
204
|
+
`pnpm -C protocol gen:check`. Fix compatibility changes only inside the
|
|
205
|
+
appropriate boundary and review the results.
|
|
206
|
+
4. **Only after the real-DSH suite passes**, widen `engines.dsh` to the explicit
|
|
207
|
+
tested versions/range. Never assume an entire future minor release is safe.
|
|
208
|
+
Update the tested range in `tools/release-plugin/check-release.mjs` with the
|
|
209
|
+
recorded evidence, keeping it aligned with the runtime compatibility guard.
|
|
210
|
+
Regenerate and validate the plugin index from `bridge/package.json`, keeping
|
|
211
|
+
its compatibility field identical.
|
|
212
|
+
5. Bump the bridge version, update these READMEs, inspect `npm pack --dry-run`,
|
|
213
|
+
and install/boot the exact tarball through the isolated plugin manager.
|
|
214
|
+
6. Audit the exact release tarball and record its SHA-256 before publication.
|
|
215
|
+
The owner signs in to npm and publishes that audited tarball with lifecycle
|
|
216
|
+
scripts disabled. Verify installation by name through DSH's plugin manager
|
|
217
|
+
in an isolated profile. Never publish a replacement over an existing version.
|
|
218
|
+
|
|
219
|
+
The public repository is a plugin-only source snapshot. Shared protocol source,
|
|
220
|
+
fixtures and integration tools remain in the private development repository;
|
|
221
|
+
monorepo build/test commands above require that maintainer checkout. The npm
|
|
222
|
+
package includes its protocol runtime and dependency license notices, so users
|
|
223
|
+
do not need those development sources. No private monorepo history, iOS app or
|
|
224
|
+
push-proxy source is included in the public repository.
|
|
225
|
+
|
|
226
|
+
Licensed under [MIT](LICENSE). See [CHANGELOG](CHANGELOG.md) for release changes.
|
|
227
|
+
|
|
228
|
+
[Source](https://github.com/JeremyCruzFang/dsh-plugin-dshm) ·
|
|
229
|
+
[Issues](https://github.com/JeremyCruzFang/dsh-plugin-dshm/issues)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# DSHM 桥接插件
|
|
2
|
+
|
|
3
|
+
[English](README.md)
|
|
4
|
+
|
|
5
|
+
通过 iPhone 或 iPad 上的 DSHM,查看和控制电脑里的 DeepSeek Harness 会话。
|
|
6
|
+
智能体仍在你的电脑上运行;手机通过局域网或你自己的 VPN 连接桥接插件。
|
|
7
|
+
|
|
8
|
+
## 环境与兼容性
|
|
9
|
+
|
|
10
|
+
- DeepSeek Harness **0.2.1-rc.3**,这是当前 `engines.dsh` 声明的精确版本。
|
|
11
|
+
DSH 仍处于 Developer Preview 阶段,不能假定新版本自动兼容。
|
|
12
|
+
- 电脑正在运行 DSH 桌面应用或 `dsh web`,手机或平板已安装兼容的 DSHM
|
|
13
|
+
构建版本。这个 npm 包不会安装 iOS 应用。
|
|
14
|
+
- DSH 运行环境使用 Node 24 或更新版本,且 PATH 中有 `openssl`,供首次
|
|
15
|
+
创建本地 TLS 证书使用。
|
|
16
|
+
- 两台设备之间能够直接通信,或已连接到你自己的 Tailscale 等 VPN。
|
|
17
|
+
|
|
18
|
+
目前已在 macOS 上使用 DSH 0.2.1-rc.3 验证桌面应用及隔离的 `dsh web`。
|
|
19
|
+
Windows 是计划支持的平台,但原生运行和防火墙验证清单尚未完成;macOS
|
|
20
|
+
通过的测试不能代替 Windows 验证。真实手机的网络测试也与本地测试客户端、
|
|
21
|
+
Simulator 的结果分别记录。v1 不包含中国大陆市场,也不声明已验证大陆网络可达性。
|
|
22
|
+
|
|
23
|
+
## 在 DSH 中安装
|
|
24
|
+
|
|
25
|
+
1. 在需要远程控制的 DSH 实例中打开 **Plugins(插件)** 页面。
|
|
26
|
+
2. 使用页面上的包安装入口,输入以下包名:
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
dsh-plugin-dshm
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
3. 让 DSH 插件管理器安装插件及依赖。按提示重启 DSH,然后打开
|
|
33
|
+
**Settings(设置)→ DSHM**。
|
|
34
|
+
|
|
35
|
+
请使用 DSH 插件管理器,不要手动修改配置文件,也不要把文件复制进已安装的
|
|
36
|
+
DSH 应用目录。安装只作用于所选的 DSH profile,不会自动启用其他 profile。
|
|
37
|
+
|
|
38
|
+
DSH 0.2.1 通过包名从 npm 安装插件,没有中央插件市场。本版本未发布 DSHM
|
|
39
|
+
自定义插件索引。
|
|
40
|
+
|
|
41
|
+
## 配对手机或平板
|
|
42
|
+
|
|
43
|
+
1. 保持 DSH 运行。在电脑上打开 **Settings → DSHM → Pair a device(配对设备)**。
|
|
44
|
+
2. 在 iPhone 或 iPad 的 DSHM 中添加电脑,扫描显示的二维码。
|
|
45
|
+
3. 出现提示时允许本地网络访问。电脑上的 DSHM 设置卡片应显示该设备为
|
|
46
|
+
**Connected(已连接)**。
|
|
47
|
+
|
|
48
|
+
二维码只能使用一次,五分钟后过期。它包含临时配对凭据,请勿转发,也不要
|
|
49
|
+
放进截图或问题报告。点击 **Cancel pairing(取消配对)** 可以提前关闭;过期
|
|
50
|
+
后重新开始配对即可。只配对你信任的设备:已配对设备可以查看会话和文件、
|
|
51
|
+
发送提示词、回答工具审批。
|
|
52
|
+
|
|
53
|
+
手机丢失或不再需要访问时,在 **Settings → DSHM** 中点击该设备的
|
|
54
|
+
**Revoke(撤销)**,再确认 **Revoke device(撤销设备)**。插件会关闭其当前
|
|
55
|
+
连接,并阻止旧配对重新连接。以后需要恢复访问时,可以重新配对。
|
|
56
|
+
|
|
57
|
+
## 网络设置
|
|
58
|
+
|
|
59
|
+
### 引导设置远程连接
|
|
60
|
+
|
|
61
|
+
手机和这台电脑不在同一 Wi-Fi?使用 Tailscale。在同一 Wi-Fi 下无需其他设置。
|
|
62
|
+
打开 **Settings → DSHM → 不在同一 Wi-Fi**。这个可选向导检查 Windows/
|
|
63
|
+
macOS 上的官方 Tailscale 程序,提供官方安装说明,并可打开 DSH 宿主电脑上的
|
|
64
|
+
Tailscale。安装、系统授权和浏览器登录由你亲自完成。如果从另一台电脑打开
|
|
65
|
+
DSH Web UI,请把 Tailscale 安装在 **运行 DSH 的电脑** 上。
|
|
66
|
+
|
|
67
|
+
手机安装 Tailscale,使用同一个个人账号登录,并连接两端。组织账号需确保
|
|
68
|
+
两台设备处于同一且允许通信的 tailnet;登录相同账号不会绕过组织访问策略。
|
|
69
|
+
连接后点 **Pair for remote access**,在 DSHM 扫描新二维码。旧的仅局域网配对
|
|
70
|
+
不会自动获得新 VPN 地址:先在 DSHM 忘记旧电脑,在宿主撤销旧设备条目,再
|
|
71
|
+
重新配对。主动生成新二维码会替换尚未使用的旧二维码。
|
|
72
|
+
|
|
73
|
+
向导区分“电脑已就绪”和“设备已通过 Tailscale 连接”。请让手机使用蜂窝网络
|
|
74
|
+
或其他 Wi-Fi 进行测试。**Pair a device** 始终保留局域网配对入口,无须
|
|
75
|
+
安装 Tailscale。取消安装、未登录或状态检查失败都不会关闭局域网配对。
|
|
76
|
+
|
|
77
|
+
插件不会自动安装 VPN,不修改 Tailscale 账号、DNS、路由、出口节点、防火墙
|
|
78
|
+
或代理设置,也不收集登录凭据。卸载插件会保留已安装的 Tailscale。新向导的全新安装及
|
|
79
|
+
远程手机验收尚未完成;此前 Windows 局域网/远程测试使用旧版包,不能代替
|
|
80
|
+
新向导验收。
|
|
81
|
+
|
|
82
|
+
- **macOS:** 在 **系统设置 → 隐私与安全性 → 本地网络** 中允许
|
|
83
|
+
**DeepSeek Harness**。如果通过终端运行 `dsh web`,也要允许相应的终端
|
|
84
|
+
应用。iOS 上的 DSHM 同样需要“本地网络”权限。
|
|
85
|
+
- **Windows:** Windows 防火墙询问 DSH 宿主程序的联网权限时,允许你信任的
|
|
86
|
+
**专用网络(Private networks)**,保持 **公用网络(Public networks)**
|
|
87
|
+
禁用。桥接插件不会替你修改防火墙规则;Windows 的运行验证仍待完成。
|
|
88
|
+
- **Wi-Fi:** 建议先让两台设备连接同一个可信的家庭或办公 Wi-Fi。访客网络、
|
|
89
|
+
手机热点或路由器的客户端隔离功能,可能让设备都能上网却无法互相连接。
|
|
90
|
+
- **代理和 VPN:** 在两台设备上开启 **绕过局域网/本地网络(bypass LAN)**,
|
|
91
|
+
或暂时关闭影响连接的代理以检查路由。局域网地址和所用 VPN 的设备地址都
|
|
92
|
+
必须可达;把全部流量送入代理的规则可能阻止配对。
|
|
93
|
+
- **不在同一 Wi-Fi:** 让电脑和手机加入同一个 Tailscale 网络或你管理的其他 VPN,
|
|
94
|
+
并允许两台设备之间通信。电脑需要保持唤醒,DSH 需要保持运行。DSHM 没有
|
|
95
|
+
自营会话流量中继。Bonjour 发现通常不会穿过 VPN;配对时应确保手机能够
|
|
96
|
+
连接电脑提供的某个地址。
|
|
97
|
+
|
|
98
|
+
桥接插件默认在局域网/私有地址及 Tailscale 地址的 TCP **47390** 端口监听,
|
|
99
|
+
与 DSH Web UI 使用不同的监听端口。不要为它设置路由器公网端口转发,也不要
|
|
100
|
+
把 DSH Web 服务改成公网监听。Bonjour 使用本地网络;如果能够发现电脑却
|
|
101
|
+
连接不上,先检查权限、代理/VPN 绕过设置及客户端隔离。
|
|
102
|
+
|
|
103
|
+
## 数据会发送到哪里
|
|
104
|
+
|
|
105
|
+
只有打开远程设置或请求远程配对时,向导才读取本机 Tailscale 状态;返回连接
|
|
106
|
+
状态和本机 VPN 地址,不返回账号身份、登录链接或其他设备清单。Tailscale 是
|
|
107
|
+
独立服务,有自己的账号和隐私条款;DSHM 在 VPN 上仍使用固定证书的 TLS。
|
|
108
|
+
|
|
109
|
+
桥接插件通过固定证书的 TLS 连接,把会话消息、工具结果、审批、所选文件及
|
|
110
|
+
已声明的交付文件发送给经过认证的已配对设备。手机发送的提示词、回答和附件
|
|
111
|
+
会交给电脑上的 DSH。桥接插件不运行云端智能体,也不使用分析服务或 DSHM
|
|
112
|
+
会话流量中继;它不会读取或转发 DSH 的模型服务凭据存储。DSH 本身仍会按照你
|
|
113
|
+
自己的配置连接模型服务和工具,遵循这些服务的设置。
|
|
114
|
+
|
|
115
|
+
Bonjour 会在局域网内公布桥接宿主的标识、协议版本和私有网络地址,供发现
|
|
116
|
+
使用。本地桥接身份和配对记录保存在 `$DSH_HOME/dshm/`,使用默认 DSH home
|
|
117
|
+
时为 `~/.dsh/dshm/`。请勿把其中的私有文件粘贴到问题报告。安装插件或使用
|
|
118
|
+
远程索引时,DSH 会访问相应的包仓库和索引服务器。
|
|
119
|
+
|
|
120
|
+
**可选的推送通知经过独立代理及 Apple 推送通知服务(APNs)。** 未配置
|
|
121
|
+
`pushProxyUrl` 时,桥接插件不会发起推送网络请求,也不会声明支持推送。
|
|
122
|
+
配置地址后会定期检查代理健康状态;只有代理可达且会话观察功能正常时,才
|
|
123
|
+
声明支持推送。本软件包包含桥接发送端,代理及应用另行提供。iOS 推送注册、
|
|
124
|
+
通知服务扩展及真实锁屏手机的通知送达仍是独立工作,本地后端测试不代表
|
|
125
|
+
这些环节已经验证。
|
|
126
|
+
|
|
127
|
+
注册推送时,应用将 APNs 设备令牌及沙盒/生产环境标识发送给所选的 HTTPS
|
|
128
|
+
代理。代理保存这份路由映射,以及用独立包装密钥加密的认证密钥。应用通过
|
|
129
|
+
DMP 将返回的注册信息和另一把通知内容密钥交给已配对的桥接插件。桥接插件
|
|
130
|
+
把这些密钥和偏好保存在私有的 `$DSH_HOME/dshm/push.json`(权限 0600)中。
|
|
131
|
+
APNs 提供方密钥只存在代理的密钥配置中,不会交给桥接插件。
|
|
132
|
+
|
|
133
|
+
配置并完成注册后,桥接插件会把加密的会话标题、简短事件摘要,以及不透明
|
|
134
|
+
推送 ID、事件类别、分组 ID 和请求签名发送给代理。代理将密文和通用备用
|
|
135
|
+
提示转交 APNs。代理及 APNs 都不会收到通知内容密钥,也无法直接读取解密后
|
|
136
|
+
的标题/摘要;路由元数据、时间和载荷大小仍然可见,代理在网络层也会收到
|
|
137
|
+
客户端 IP。应用仅记录计数,并保存用于限流的 IP 哈希。推送不会上传文件或
|
|
138
|
+
完整会话记录;设备保持已认证的实时连接时,不会向该设备发送推送。
|
|
139
|
+
|
|
140
|
+
取消推送注册或撤销设备会先删除本地推送注册,再尽力请求代理删除相应映射。
|
|
141
|
+
代理不可达时,无法确认远端删除成功;仅卸载软件包不会删除远端映射。
|
|
142
|
+
APNs 已经接收的通知无法撤回。终端输出仍仅供查看;桥接插件不提供可交互的
|
|
143
|
+
远程终端。
|
|
144
|
+
|
|
145
|
+
## 卸载
|
|
146
|
+
|
|
147
|
+
1. 在 **Settings → DSHM** 中撤销不再需要授权的设备。
|
|
148
|
+
2. 打开 **Plugins**,找到 `dsh-plugin-dshm`,通过 DSH 插件管理器从当前
|
|
149
|
+
profile 中移除。如果其他 profile 也安装过,包括可选的 `dshm` CLI
|
|
150
|
+
profile,请分别移除。
|
|
151
|
+
3. 按提示重启受影响的 DSH 宿主。该宿主的 DSHM 设置卡片和监听端口应已消失。
|
|
152
|
+
|
|
153
|
+
卸载软件包与删除私有身份、配对记录是两件事。如果打算重新安装,请保留
|
|
154
|
+
`$DSH_HOME/dshm/`。如果你明确选择完整重置,应先停止所有使用该 home 的 DSH
|
|
155
|
+
宿主,然后仅删除桥接插件的 `dshm` 状态目录;已有设备需要忘记旧电脑并重新
|
|
156
|
+
配对。不要删除整个 DSH home,也不要删除模型服务凭据或会话目录。卸载桥接
|
|
157
|
+
插件不会删除 DSH 会话。
|
|
158
|
+
|
|
159
|
+
## 新 DSH 版本发布检查清单(维护者)
|
|
160
|
+
|
|
161
|
+
1. 测试期间保持当前已验证的 `engines.dsh` 值不变,先阅读上游改动,尤其是
|
|
162
|
+
projection 接口和插件加载器的变化。
|
|
163
|
+
2. 通过 DSH 的正常发布渠道安装候选运行时,在隔离的 `.dsh-test` home 中对
|
|
164
|
+
**该候选版本**运行 `pnpm -C bridge test:integration`。兼容性改动必须同时
|
|
165
|
+
审查 `bridge/src/projection/native.ts` 中的显式运行时版本保护;只改包元数据
|
|
166
|
+
不会启用新运行时。必要时调整测试宿主路径,但不要跳过失败,也不要用旧
|
|
167
|
+
运行时的结果冒充新版本验证。
|
|
168
|
+
记录实际版本和结果;声明新的 Windows 组合已支持前,完成 Windows 清单。
|
|
169
|
+
3. 运行 `pnpm -C bridge test`、`pnpm -C protocol validate` 和
|
|
170
|
+
`pnpm -C protocol gen:check`。在正确的架构边界内修复兼容性问题并审查结果。
|
|
171
|
+
4. **只有真实 DSH 集成测试通过后**,才把 `engines.dsh` 扩大到明确验证过的
|
|
172
|
+
版本或范围。不要假定未来整个小版本都兼容。根据实际验证记录,更新
|
|
173
|
+
`tools/release-plugin/check-release.mjs` 中的已测试范围,并与运行时版本保护
|
|
174
|
+
保持一致。从 `bridge/package.json`
|
|
175
|
+
重新生成并验证插件索引,保证两处兼容性字段一致。
|
|
176
|
+
5. 提升插件版本,更新中英文 README,检查 `npm pack --dry-run`,并通过隔离
|
|
177
|
+
profile 的插件管理器安装和启动准备发布的同一个 tarball。
|
|
178
|
+
6. 发布前审计准备发布的同一个 tarball,记录 SHA-256。所有者亲自登录 npm,
|
|
179
|
+
禁用生命周期脚本后发布该文件。通过隔离 profile 的 DSH 插件管理器验证按名
|
|
180
|
+
安装。已经发布的版本不能通过覆盖来修复。
|
|
181
|
+
|
|
182
|
+
公开仓库仅保存插件源码快照。共用协议源码、fixtures 及集成工具保留在私有
|
|
183
|
+
开发仓库中;上述 monorepo 构建和测试命令需要维护者的开发检出。npm 包已包含
|
|
184
|
+
协议运行时和依赖许可证,用户不需要这些开发源码。公开仓库不包含私有仓库
|
|
185
|
+
历史、iOS 应用或推送代理源码。
|
|
186
|
+
|
|
187
|
+
采用 [MIT 许可证](LICENSE)。版本改动见 [CHANGELOG](CHANGELOG.md)。
|
|
188
|
+
|
|
189
|
+
[项目源码](https://github.com/JeremyCruzFang/dsh-plugin-dshm) ·
|
|
190
|
+
[问题反馈](https://github.com/JeremyCruzFang/dsh-plugin-dshm/issues)
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
export declare const authMessage: (nonce: string, hostId: string, fingerprint: string) => Buffer;
|
|
3
|
+
export declare function publicKeyFromSpki(value: string): crypto.KeyObject;
|
|
4
|
+
export declare function verifySignature(publicKey: string, nonce: string, hostId: string, fingerprint: string, signature: string): boolean;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
export const authMessage = (nonce, hostId, fingerprint) => Buffer.concat([
|
|
3
|
+
Buffer.from('dshm-auth-v1'), Buffer.from(nonce, 'base64url'), Buffer.from(hostId), Buffer.from(fingerprint),
|
|
4
|
+
]);
|
|
5
|
+
export function publicKeyFromSpki(value) {
|
|
6
|
+
const bytes = Buffer.from(value, 'base64');
|
|
7
|
+
if (bytes.toString('base64') !== value || bytes.length > 256)
|
|
8
|
+
throw new Error('Invalid public key encoding');
|
|
9
|
+
const key = crypto.createPublicKey({ key: bytes, type: 'spki', format: 'der' });
|
|
10
|
+
if (key.asymmetricKeyType !== 'ec' || key.asymmetricKeyDetails?.namedCurve !== 'prime256v1')
|
|
11
|
+
throw new Error('P-256 key required');
|
|
12
|
+
return key;
|
|
13
|
+
}
|
|
14
|
+
export function verifySignature(publicKey, nonce, hostId, fingerprint, signature) {
|
|
15
|
+
try {
|
|
16
|
+
const bytes = Buffer.from(signature, 'base64');
|
|
17
|
+
if (bytes.toString('base64') !== signature || bytes.length > 80)
|
|
18
|
+
return false;
|
|
19
|
+
return crypto.verify('sha256', authMessage(nonce, hostId, fingerprint), { key: publicKeyFromSpki(publicKey), dsaEncoding: 'der' }, bytes);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
package/lib/cli/index.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import QRCode from 'qrcode';
|
|
2
|
+
import { parseConfig } from '../config.js';
|
|
3
|
+
import { localRequest } from '../host/local.js';
|
|
4
|
+
import { installCli, cliInject } from '../projection/host.js';
|
|
5
|
+
export const name = 'dshm-cli';
|
|
6
|
+
export const inject = cliInject;
|
|
7
|
+
export async function run(args) {
|
|
8
|
+
const directory = parseConfig(undefined).stateDir;
|
|
9
|
+
const [command, id, ...extra] = args;
|
|
10
|
+
if (extra.length || !['pair', 'devices', 'revoke', 'status'].includes(command ?? '') || (command === 'revoke' ? !id : id !== undefined)) {
|
|
11
|
+
console.error('Usage: dsh dshm pair | devices | revoke <id> | status');
|
|
12
|
+
return 2;
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
if (command === 'pair') {
|
|
16
|
+
const value = await localRequest(directory, 'POST', '/pair', {});
|
|
17
|
+
console.log(await QRCode.toString(value.url, { type: 'terminal', small: true }));
|
|
18
|
+
console.log(`Pairing expires at ${value.expiresAt}. One use. Keep this QR private.`);
|
|
19
|
+
}
|
|
20
|
+
else if (command === 'devices') {
|
|
21
|
+
const { devices } = await localRequest(directory, 'GET', '/devices');
|
|
22
|
+
console.log(JSON.stringify(devices, null, 2));
|
|
23
|
+
}
|
|
24
|
+
else if (command === 'revoke') {
|
|
25
|
+
const result = await localRequest(directory, 'POST', '/revoke', { deviceId: id });
|
|
26
|
+
if (!result.revoked) {
|
|
27
|
+
console.error('Device not found');
|
|
28
|
+
return 1;
|
|
29
|
+
}
|
|
30
|
+
console.log('Device revoked');
|
|
31
|
+
}
|
|
32
|
+
else
|
|
33
|
+
console.log(JSON.stringify(await localRequest(directory, 'GET', '/status'), null, 2));
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
console.error('DSHM bridge is unavailable in this DSH_HOME. Start the host profile first.');
|
|
38
|
+
return 1;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export function apply(context) { installCli(context, run); }
|