dsh-plugin-tether 0.1.25 → 0.1.26
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 +10 -0
- package/README.md +44 -0
- package/README.zh.md +44 -0
- package/index.js +18 -12
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
本文件记录面向用户的变化。每个版本的这一节会原样作为该版本 Release 的说明。
|
|
4
4
|
|
|
5
|
+
## 0.1.26
|
|
6
|
+
|
|
7
|
+
### 修复
|
|
8
|
+
|
|
9
|
+
- **dsh 0.2.2-rc 上手机打开侧栏变成一块黑、点不动**。0.2.2-rc 起 dsh 在 <768px 自带抽屉:主框架挂 `data-sidebar-drawer`,并渲染一层 `z-index:70` 的遮罩;tether 注入的窄屏抽屉把侧栏钉成 `z-index:30`,侧栏于是被原生遮罩压到下面——深色主题下遮罩是 50% 黑,侧栏看起来就是一块黑,遮罩的 `pointer-events:auto` 又把点击全吞了。现在这段手工抽屉只在 dsh 没有原生抽屉(框架不带 `data-sidebar-drawer`)时生效,原生抽屉出现时整体让位:滑入滑出、遮罩、点外收起都交给 dsh 自己,侧栏里的「连接手机/我的电脑」按钮照常挂载;点外收起那段脚本同样只在没有原生抽屉时接管。老版本 dsh 行为不变。
|
|
10
|
+
|
|
11
|
+
### English
|
|
12
|
+
|
|
13
|
+
On dsh 0.2.2-rc and later the sidebar turned into a black block and stopped responding when opened on a phone. Since 0.2.2-rc dsh ships its own drawer below 768px: the frame carries `data-sidebar-drawer` and renders a mask at `z-index:70`, while tether's injected narrow-screen drawer pinned the sidebar to `z-index:30`, so the native mask stacked on top — in dark mode that mask is 50% black, which is exactly the black block, and its `pointer-events:auto` swallowed every tap. The hand-rolled drawer now only applies when dsh has no native drawer (the frame lacks `data-sidebar-drawer`) and steps aside when the native drawer is present, leaving the slide-in/out, the mask and tap-outside-to-close to dsh itself; the "Connect a phone / My computers" button still mounts as usual. Behaviour on older dsh versions is unchanged.
|
|
14
|
+
|
|
5
15
|
## 0.1.25
|
|
6
16
|
|
|
7
17
|
### 修复
|
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
<p align="center"><sub>An independent community project. Not affiliated with, partnered with, authorised by, or endorsed by DeepSeek.<br>No DeepSeek employee or upstream DeepSeek Harness team member is involved in this repository.<br><a href="README.zh.md">中文</a> · English</sub></p>
|
|
10
10
|
|
|
11
|
+
<p align="center"><sub>Official repository: <a href="https://github.com/zexadev/dsh-tether">github.com/zexadev/dsh-tether</a> — releases and issues live here; forks are not maintained by this project.<br>手机远程使用电脑上的 DeepSeek Harness(dsh):跨网点对点直连、不用架服务器;Android 还能把 dsh 跑在手机本地。</sub></p>
|
|
12
|
+
|
|
11
13
|
<p align="center">
|
|
12
14
|
<img src="assets/banner.jpg" alt="Phone tethered directly to a dev machine" width="100%">
|
|
13
15
|
</p>
|
|
@@ -147,6 +149,48 @@ Pairing (including a wrong code being refused), approval delivery, and switching
|
|
|
147
149
|
|
|
148
150
|
Local mode was verified on a Redmi running Android 16: a fresh install reaches a working interface in 9.1 seconds (runtime unpacking included) and later starts take 2.1 seconds; the node process survives 30 seconds in the background; force-stopping the app and reopening it restores local mode automatically.
|
|
149
151
|
|
|
152
|
+
## FAQ
|
|
153
|
+
|
|
154
|
+
### Do I need a public IP, a server of my own, or the same Wi-Fi?
|
|
155
|
+
|
|
156
|
+
No. The phone and the machine hole-punch to each other through iroh; there is no account and nothing to deploy. Only a failed punch falls back to a relay, and that relay carries ciphertext it cannot read. If your phone only ever sits on the same Wi-Fi as your machine, a plain LAN setup is simpler and you do not need this.
|
|
157
|
+
|
|
158
|
+
### Does it work with the phone on 4G/5G and the machine on home broadband?
|
|
159
|
+
|
|
160
|
+
Yes, and that is the path that has been verified on a real device: Wi-Fi off, 5G only, machine on home broadband, the plugin reported a direct public path and the relay was never used (see [What has been verified](#what-has-been-verified)). The relay fallback itself has not yet been triggered on a real network.
|
|
161
|
+
|
|
162
|
+
### Is there an iOS app?
|
|
163
|
+
|
|
164
|
+
A beta. Every release ships an unsigned IPA; sign it yourself with AltStore, Sideloadly or similar (a free Apple ID expires after 7 days). It is built only in CI and this project has never run it on a real device. Local mode is Android-only, because iOS forbids child processes.
|
|
165
|
+
|
|
166
|
+
### Can I use it with no computer at all?
|
|
167
|
+
|
|
168
|
+
On Android, yes. The `arm64` APK bundles Node 24 and dsh `0.2.1-rc.2`; **Hosts → Run on this phone** starts DSH on the phone itself, with no Termux, no commands and no root. That bundle is why the `arm64` APK is about 83 MB. The phone has no bash and no full coreutils, so shell-dependent tools are incomplete; chat and file read/write are unaffected.
|
|
169
|
+
|
|
170
|
+
### Can I open it as a web page (H5) or a WeChat mini program instead of installing the app?
|
|
171
|
+
|
|
172
|
+
No. The app owns an iroh endpoint (QUIC with a custom ALPN) and feeds the DSH interface into its WebView through a loopback proxy; a browser page cannot make that connection, and a mini program's `<web-view>` only loads whitelisted business domains. Doing it from a browser would need a server in the middle, which is exactly what this project avoids ([#11](https://github.com/zexadev/dsh-tether/issues/11)).
|
|
173
|
+
|
|
174
|
+
### Which dsh versions are supported?
|
|
175
|
+
|
|
176
|
+
The list under [Known limitations](#known-limitations), currently `0.1.0-rc.7` through `0.2.2-alpha.2`. From dsh 0.1.7 the install is refused outright when the declared range does not cover your dsh, so an unsupported version fails at install time instead of silently misbehaving.
|
|
177
|
+
|
|
178
|
+
### The interface sits at "Loading workspace…", or "Select workspace" reports `AbortSignal.any is not a function`
|
|
179
|
+
|
|
180
|
+
Fixed in 0.1.24. Older system WebViews (Huawei and others still ship Chromium 114) lack `Promise.withResolvers` and `AbortSignal.any`, which the dsh 0.2.1-rc frontend uses; the app now supplies both when the WebView lacks them ([#20](https://github.com/zexadev/dsh-tether/issues/20)).
|
|
181
|
+
|
|
182
|
+
### After sitting idle the app is stuck on "Reconnecting"
|
|
183
|
+
|
|
184
|
+
Fixed in 0.1.24 ([#19](https://github.com/zexadev/dsh-tether/issues/19)): a dead link was never reported and the phone-side proxy port was not released. Upgrade to 0.1.24 or later.
|
|
185
|
+
|
|
186
|
+
### How is this different from ds-harness-remote or DSH Desktop?
|
|
187
|
+
|
|
188
|
+
See the table under [The case it solves](#compared-with-similar-projects). In short: no account and no server here, direct first with a ciphertext-only relay as fallback, Android local mode, MIT; ds-harness-remote signs in to its service and offers PC / Android / Web; DSH Desktop expects the same Wi-Fi or a Tailscale network you set up.
|
|
189
|
+
|
|
190
|
+
### Is this an official DeepSeek project?
|
|
191
|
+
|
|
192
|
+
No. It is an independent community project; see [Relationship to DeepSeek Harness](#relationship-to-deepseek-harness).
|
|
193
|
+
|
|
150
194
|
## Relationship to DeepSeek Harness
|
|
151
195
|
|
|
152
196
|
<p align="center"><img src="assets/dsh-mark.svg" height="36" alt="DeepSeek Harness"></p>
|
package/README.zh.md
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
<p align="center"><sub>独立的社区开源项目,与深度求索不存在隶属、合作、授权或背书关系。<br>本仓库无深度求索员工或 DeepSeek Harness 上游官方团队成员参与。<br>中文 · <a href="README.md">English</a></sub></p>
|
|
10
10
|
|
|
11
|
+
<p align="center"><sub>官方仓库:<a href="https://github.com/zexadev/dsh-tether">github.com/zexadev/dsh-tether</a>,发版与 issue 都在这里;各 fork 不由本仓维护。<br>DeepSeek Harness (dsh) remote access from your phone: Android / iOS client, peer-to-peer across networks, no server to set up; Android can also run dsh locally.</sub></p>
|
|
12
|
+
|
|
11
13
|
<p align="center">
|
|
12
14
|
<img src="assets/banner.jpg" alt="手机与开发机直接相连" width="100%">
|
|
13
15
|
</p>
|
|
@@ -154,6 +156,48 @@ dsh plugin --profile web add .
|
|
|
154
156
|
|
|
155
157
|
本地模式在 Redmi(Android 16)真机验证:全新安装后首次启动到界面出现 9.1 秒(含解压运行时),之后启动 2.1 秒;退后台 30 秒 node 进程仍在;强杀 App 后重开自动恢复到本地模式。
|
|
156
158
|
|
|
159
|
+
## 常见问题
|
|
160
|
+
|
|
161
|
+
### 需要公网 IP、自己的服务器,或者同一个 WiFi 吗?
|
|
162
|
+
|
|
163
|
+
都不需要。手机和电脑通过 iroh 互相打洞直连,不注册账号、不部署任何东西;打不通才退回 relay,relay 上过的只是它读不懂的密文。如果你的手机永远和电脑在同一个 WiFi 里,直接走局域网更简单,用不上这个。
|
|
164
|
+
|
|
165
|
+
### 手机走 4G/5G、电脑在家宽,能连上吗?
|
|
166
|
+
|
|
167
|
+
能,而且这正是真机验证过的那条路:手机关 WiFi 只走 5G、电脑在家宽,插件侧报出公网直连路径,relay 全程没用上(见[验证过什么](#验证过什么))。打洞失败退回 relay 这条路径本身,尚未在真实网络下触发过。
|
|
168
|
+
|
|
169
|
+
### 有 iOS 版吗?
|
|
170
|
+
|
|
171
|
+
有,测试版。每个 Release 都带未签名的 ipa,用 AltStore、Sideloadly 一类工具自签安装(免费 Apple ID 签出来的 7 天过期)。它只在 CI 上构建,本项目没有在真机上跑过。本地模式只有 Android 有,iOS 禁止子进程。
|
|
172
|
+
|
|
173
|
+
### 手边完全没有电脑,能用吗?
|
|
174
|
+
|
|
175
|
+
Android 可以。`arm64` 包内置了 Node 24 和 dsh `0.2.1-rc.2`,**主机 → 在本机运行**就能在手机上把 DSH 跑起来,不装 Termux、不敲命令、不用 root;arm64 包约 83 MB 就是因为这个。手机上没有 bash 和完整 coreutils,依赖 shell 的工具用不全,对话和读写文件不受影响。
|
|
176
|
+
|
|
177
|
+
### 能不装 App,用手机网页(H5)或微信小程序访问吗?
|
|
178
|
+
|
|
179
|
+
不能。App 自己带一个 iroh 端点(自定义 ALPN 的 QUIC),再经手机本地的回环代理把 DSH 界面灌进 WebView;浏览器页面建不起这种连接,小程序的 `<web-view>` 也只能加载白名单里的业务域名。要在浏览器里用,中间必须常驻一台服务器,而这正是本项目要避开的([#11](https://github.com/zexadev/dsh-tether/issues/11))。
|
|
180
|
+
|
|
181
|
+
### 支持哪些 dsh 版本?
|
|
182
|
+
|
|
183
|
+
见[已知限制](#已知限制)里那一行,目前是 `0.1.0-rc.7` 到 `0.2.2-alpha.2`。dsh 0.1.7 起,声明范围没覆盖到的 dsh 会在安装时直接拒绝,所以不支持的版本是装不上,而不是装上了乱跑。
|
|
184
|
+
|
|
185
|
+
### 界面停在「正在加载工作区…」,或点「选择工作区」报 `AbortSignal.any is not a function`
|
|
186
|
+
|
|
187
|
+
0.1.24 已修。华为等厂商随系统发的旧 WebView 还停在 Chromium 114,没有 dsh 0.2.1-rc 前端用到的 `Promise.withResolvers` 和 `AbortSignal.any`;现在 App 在 WebView 缺这两个 API 时自行补上([#20](https://github.com/zexadev/dsh-tether/issues/20))。
|
|
188
|
+
|
|
189
|
+
### 放一段时间后卡在「重新连接中」不恢复
|
|
190
|
+
|
|
191
|
+
0.1.24 已修([#19](https://github.com/zexadev/dsh-tether/issues/19)):断链没有上报、手机侧代理端口没有释放。升级到 0.1.24 及以上。
|
|
192
|
+
|
|
193
|
+
### 和 ds-harness-remote、DSH Desktop 有什么区别?
|
|
194
|
+
|
|
195
|
+
见[它解决什么](#与同类项目的区别)下面的表。一句话:这里不注册、不架服务器,直连优先、退回时 relay 只见密文,Android 有本地模式,MIT;ds-harness-remote 要登录它的服务,提供 PC / Android / Web;DSH Desktop 要同一个 WiFi 或你自己搭的 Tailscale 网络。
|
|
196
|
+
|
|
197
|
+
### 这是 DeepSeek 官方项目吗?
|
|
198
|
+
|
|
199
|
+
不是,是独立的社区项目,见[与 DeepSeek Harness 的关系](#与-deepseek-harness-的关系)。
|
|
200
|
+
|
|
157
201
|
## 与 DeepSeek Harness 的关系
|
|
158
202
|
|
|
159
203
|
<p align="center"><img src="assets/dsh-mark.svg" height="36" alt="DeepSeek Harness"></p>
|
package/index.js
CHANGED
|
@@ -500,14 +500,18 @@ const tetherCss = `
|
|
|
500
500
|
/* 只认最外层那个 frame。dsh 里好几个组件的局部类名也带 _frame(会话区、
|
|
501
501
|
附件缩略图、子代理、文档预览),它们都长在它里面:附件缩略图自己是个
|
|
502
502
|
单格网格,被这条列模板改掉后图片会挤进 56px 的第一列。 */
|
|
503
|
-
|
|
503
|
+
/* dsh 0.2.2-rc 起在 <768px 自带抽屉:frame 挂 data-sidebar-drawer,自带
|
|
504
|
+
遮罩(z-index 70)与滑入动画。这段手工抽屉只服务没有原生抽屉的旧版本,
|
|
505
|
+
原生抽屉出现时整体让位——否则我们的 z-index:30 会落到原生遮罩(70)下面,
|
|
506
|
+
侧栏被遮罩压成一块黑、点也点不到。 */
|
|
507
|
+
[class*="_frame"]:not([class*="_frame"] *):not([data-sidebar-drawer]) {
|
|
504
508
|
grid-template-columns: 56px minmax(0, 1fr) 0px !important;
|
|
505
509
|
}
|
|
506
|
-
[class*="_frame"] > [class*="centerCol"] { grid-column: 2 !important; }
|
|
510
|
+
[class*="_frame"]:not([data-sidebar-drawer]) > [class*="centerCol"] { grid-column: 2 !important; }
|
|
507
511
|
/* 右列 dsh 0.1.5 起从 detailsCol 改名 rightbarCol,两个名字都钉住 */
|
|
508
|
-
[class*="_frame"] > [class*="detailsCol"],
|
|
509
|
-
[class*="_frame"] > [class*="rightbarCol"] { grid-column: 3 !important; }
|
|
510
|
-
[class*="_frame"] > [class*="sidebarCol"] {
|
|
512
|
+
[class*="_frame"]:not([data-sidebar-drawer]) > [class*="detailsCol"],
|
|
513
|
+
[class*="_frame"]:not([data-sidebar-drawer]) > [class*="rightbarCol"] { grid-column: 3 !important; }
|
|
514
|
+
[class*="_frame"]:not([data-sidebar-drawer]) > [class*="sidebarCol"] {
|
|
511
515
|
position: absolute !important;
|
|
512
516
|
top: 0;
|
|
513
517
|
bottom: 0;
|
|
@@ -516,13 +520,13 @@ const tetherCss = `
|
|
|
516
520
|
z-index: 30 !important;
|
|
517
521
|
transition: width 220ms ease, box-shadow 220ms ease;
|
|
518
522
|
}
|
|
519
|
-
[class*="_frame"]:not([data-sidebar-collapsed="true"]) > [class*="sidebarCol"] {
|
|
523
|
+
[class*="_frame"]:not([data-sidebar-drawer]):not([data-sidebar-collapsed="true"]) > [class*="sidebarCol"] {
|
|
520
524
|
width: min(300px, 84vw) !important;
|
|
521
525
|
box-shadow: 0 10px 36px rgba(0, 0, 0, 0.24);
|
|
522
526
|
}
|
|
523
527
|
/* 抽屉下的内容压暗。指针不拦——收起由注入的脚本接管,拦了反而会在脚本
|
|
524
528
|
未生效时把整页点死。 */
|
|
525
|
-
[class*="_frame"]:not([class*="_frame"] *)::after {
|
|
529
|
+
[class*="_frame"]:not([class*="_frame"] *):not([data-sidebar-drawer])::after {
|
|
526
530
|
content: '';
|
|
527
531
|
position: absolute;
|
|
528
532
|
inset: 0;
|
|
@@ -532,15 +536,15 @@ const tetherCss = `
|
|
|
532
536
|
pointer-events: none;
|
|
533
537
|
transition: opacity 220ms ease;
|
|
534
538
|
}
|
|
535
|
-
[class*="_frame"]:not([class*="_frame"] *):not([data-sidebar-collapsed="true"])::after { opacity: 1; }
|
|
536
|
-
[class*="_frame"] > [class*="_handle"] { display: none !important; }
|
|
539
|
+
[class*="_frame"]:not([class*="_frame"] *):not([data-sidebar-drawer]):not([data-sidebar-collapsed="true"])::after { opacity: 1; }
|
|
540
|
+
[class*="_frame"]:not([data-sidebar-drawer]) > [class*="_handle"] { display: none !important; }
|
|
537
541
|
|
|
538
542
|
/* 侧栏收起时是图标条,「主机」按钮的文字跟着藏起来,和 dsh 自己的按钮一致 */
|
|
539
543
|
[data-dsh-tether="hosts-label"] { display: none; }
|
|
540
544
|
[class*="_frame"]:not([data-sidebar-collapsed="true"]) [data-dsh-tether="hosts-label"] { display: inline; }
|
|
541
545
|
@media (prefers-reduced-motion: reduce) {
|
|
542
|
-
[class*="_frame"] > [class*="sidebarCol"],
|
|
543
|
-
[class*="_frame"]::after { transition: none; }
|
|
546
|
+
[class*="_frame"]:not([data-sidebar-drawer]) > [class*="sidebarCol"],
|
|
547
|
+
[class*="_frame"]:not([data-sidebar-drawer])::after { transition: none; }
|
|
544
548
|
}
|
|
545
549
|
|
|
546
550
|
/* 触摸时安卓 WebView 会按元素的 DOM 盒子刷一块蓝色高亮,方角、盖住圆角,
|
|
@@ -573,8 +577,10 @@ const tetherScript = `
|
|
|
573
577
|
document.addEventListener('pointerdown', function (event) {
|
|
574
578
|
if (!narrow.matches) return
|
|
575
579
|
var frame = document.querySelector('[class*="_frame"]')
|
|
580
|
+
// dsh 0.2.2-rc 起自带抽屉,遮罩自己会点外收起;这里只补没有原生抽屉的旧版
|
|
581
|
+
if (!frame || frame.hasAttribute('data-sidebar-drawer')) return
|
|
576
582
|
// 抽屉开着才有「点外面收起来」可言;判据和样式那边同一个
|
|
577
|
-
if (
|
|
583
|
+
if (frame.getAttribute('data-sidebar-collapsed') === 'true') return
|
|
578
584
|
var drawer = frame.querySelector(':scope > [class*="sidebarCol"]')
|
|
579
585
|
if (!drawer || drawer.contains(event.target)) return
|
|
580
586
|
var toggle = document.querySelector('button[aria-label*="侧边栏"], button[aria-label*="sidebar" i]')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-tether",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.26",
|
|
4
4
|
"description": "Mobile client for the DeepSeek Harness — use the dsh on your dev machine from your Android or iOS phone, remotely across networks, peer-to-peer over iroh with no server to set up (falls back to a relay that only sees ciphertext)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
|
@@ -56,11 +56,11 @@
|
|
|
56
56
|
"@deepseek-ai/dsh-user-approval": { "optional": true }
|
|
57
57
|
},
|
|
58
58
|
"optionalDependencies": {
|
|
59
|
-
"dsh-tether-host-android-arm64": "0.1.
|
|
60
|
-
"dsh-tether-host-darwin-arm64": "0.1.
|
|
61
|
-
"dsh-tether-host-darwin-x64": "0.1.
|
|
62
|
-
"dsh-tether-host-linux-arm64": "0.1.
|
|
63
|
-
"dsh-tether-host-linux-x64": "0.1.
|
|
64
|
-
"dsh-tether-host-win32-x64": "0.1.
|
|
59
|
+
"dsh-tether-host-android-arm64": "0.1.26",
|
|
60
|
+
"dsh-tether-host-darwin-arm64": "0.1.26",
|
|
61
|
+
"dsh-tether-host-darwin-x64": "0.1.26",
|
|
62
|
+
"dsh-tether-host-linux-arm64": "0.1.26",
|
|
63
|
+
"dsh-tether-host-linux-x64": "0.1.26",
|
|
64
|
+
"dsh-tether-host-win32-x64": "0.1.26"
|
|
65
65
|
}
|
|
66
66
|
}
|