dsh-plugin-tether 0.1.8 → 0.1.9
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 +12 -0
- package/README.md +4 -2
- package/README.zh.md +4 -2
- package/index.js +38 -0
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
本文件记录面向用户的变化。每个版本的这一节会原样作为该版本 Release 的说明。
|
|
4
4
|
|
|
5
|
+
## 0.1.9
|
|
6
|
+
|
|
7
|
+
### 新增
|
|
8
|
+
|
|
9
|
+
- **适配 dsh 0.1.2-alpha 的浏览器认证**([#4](https://github.com/zexadev/dsh-tether/issues/4))。dsh 0.1.2-alpha 起,网页界面与 Host API 要求持有经启动 token 兑换的签名 cookie,无凭据一律 401——手机端表现为连上后一片 401 提示。
|
|
10
|
+
|
|
11
|
+
适配完全在电脑侧完成:插件启动时自动完成 token→cookie 兑换,sidecar 在代理出口把认证注入每个转发请求。**手机 App 无需更新**;dsh 的跨站请求防护经隧道原样保留(伪造来源仍被 403 拒绝)。
|
|
12
|
+
|
|
13
|
+
cookie 是 `SameSite=Strict` 且绑定地址端口,手机 WebView 的内嵌页面属跨站上下文、cookie 根本不会随请求发出,所以「把登录链接发给手机打开」这条路在浏览器规则下走不通,注入只能发生在电脑侧。
|
|
14
|
+
|
|
15
|
+
- 继续兼容 dsh 0.1.0-rc.7 / rc.8:旧版没有浏览器认证,代理保持原样透传,行为不变。
|
|
16
|
+
|
|
5
17
|
## 0.1.8
|
|
6
18
|
|
|
7
19
|
### 修复
|
package/README.md
CHANGED
|
@@ -17,9 +17,11 @@
|
|
|
17
17
|
<a href="../../releases"><img src="https://img.shields.io/github/downloads/zexadev/dsh-tether/total?style=flat&label=downloads&color=4D6BFE" alt="Downloads"></a>
|
|
18
18
|
<a href="../../stargazers"><img src="https://img.shields.io/github/stars/zexadev/dsh-tether?style=flat&label=%E2%98%85&color=08C" alt="Stars"></a>
|
|
19
19
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-2EA44F?style=flat" alt="MIT"></a>
|
|
20
|
-
<img src="https://img.shields.io/badge/dsh-0.1.0--rc.7%20%7C%20rc.8-4D6BFE?style=flat" alt="dsh 0.1.0-rc.7 | rc.8">
|
|
20
|
+
<img src="https://img.shields.io/badge/dsh-0.1.0--rc.7%20%7C%20rc.8%20%7C%200.1.2--alpha-4D6BFE?style=flat" alt="dsh 0.1.0-rc.7 | rc.8 | 0.1.2-alpha">
|
|
21
21
|
<img src="https://img.shields.io/badge/Android-4493F8?style=flat" alt="Android">
|
|
22
22
|
<img src="https://img.shields.io/badge/iOS-beta-8E8E93?style=flat" alt="iOS beta">
|
|
23
|
+
<a href="https://www.dsh.so/artifact/dsh-tether"><img src="https://www.dsh.so/badge/dsh-tether.svg" alt="dsh.so security scan"></a>
|
|
24
|
+
<a href="https://www.dsh.so/artifact/dsh-tether"><img src="https://www.dsh.so/badge/install/dsh-tether.svg" alt="dsh.so install check"></a>
|
|
23
25
|
</p>
|
|
24
26
|
|
|
25
27
|
<p align="center">
|
|
@@ -106,7 +108,7 @@ From then on the app connects by itself when you open it.
|
|
|
106
108
|
- The iOS build is beta: built only in CI, never run on a real device, and you sign it yourself. Android is the one verified on real hardware.
|
|
107
109
|
- The app connects when you open it and holds no background connection — Android's doze would not let it anyway.
|
|
108
110
|
- The interface on the phone is DSH's own; the narrow-screen fit comes from minimal injected styles, so a dsh layout change may need a follow-up here.
|
|
109
|
-
- Verified against dsh **`0.1.0-rc.7
|
|
111
|
+
- Verified against dsh **`0.1.0-rc.7`**, **`0.1.0-rc.8`** and **`0.1.2-alpha`**. dsh is in developer preview — check this line before assuming a newer dsh works. The browser authentication dsh introduced in 0.1.2-alpha is handled entirely on the machine side; the phone app needs no update for it.
|
|
110
112
|
|
|
111
113
|
## What has been verified
|
|
112
114
|
|
package/README.zh.md
CHANGED
|
@@ -17,9 +17,11 @@
|
|
|
17
17
|
<a href="../../releases"><img src="https://img.shields.io/github/downloads/zexadev/dsh-tether/total?style=flat&label=downloads&color=4D6BFE" alt="下载量"></a>
|
|
18
18
|
<a href="../../stargazers"><img src="https://img.shields.io/github/stars/zexadev/dsh-tether?style=flat&label=%E2%98%85&color=08C" alt="Stars"></a>
|
|
19
19
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-2EA44F?style=flat" alt="MIT"></a>
|
|
20
|
-
<img src="https://img.shields.io/badge/dsh-0.1.0--rc.7%20%7C%20rc.8-4D6BFE?style=flat" alt="dsh 0.1.0-rc.7 | rc.8">
|
|
20
|
+
<img src="https://img.shields.io/badge/dsh-0.1.0--rc.7%20%7C%20rc.8%20%7C%200.1.2--alpha-4D6BFE?style=flat" alt="dsh 0.1.0-rc.7 | rc.8 | 0.1.2-alpha">
|
|
21
21
|
<img src="https://img.shields.io/badge/Android-4493F8?style=flat" alt="Android">
|
|
22
22
|
<img src="https://img.shields.io/badge/iOS-%E6%B5%8B%E8%AF%95%E7%89%88-8E8E93?style=flat" alt="iOS 测试版">
|
|
23
|
+
<a href="https://www.dsh.so/artifact/dsh-tether"><img src="https://www.dsh.so/badge/dsh-tether.svg" alt="dsh.so 安全扫描"></a>
|
|
24
|
+
<a href="https://www.dsh.so/artifact/dsh-tether"><img src="https://www.dsh.so/badge/install/dsh-tether.svg" alt="dsh.so 安装实测"></a>
|
|
23
25
|
</p>
|
|
24
26
|
|
|
25
27
|
<p align="center">
|
|
@@ -106,7 +108,7 @@ dsh plugin --profile web add .
|
|
|
106
108
|
- iOS 版是测试版:只在 CI 上构建,从未在真机运行过,且需要自行签名。安卓版是经过真机验证的那一个。
|
|
107
109
|
- App 打开时才连接,不在后台常驻——Android 的 doze 也留不住它。
|
|
108
110
|
- 手机上的界面是 DSH 自己的,窄屏适配靠注入的最小样式完成;dsh 改版式时可能需要跟进。
|
|
109
|
-
- 已针对 dsh **`0.1.0-rc.7`** 与 **`0.1.
|
|
111
|
+
- 已针对 dsh **`0.1.0-rc.7`**、**`0.1.0-rc.8`** 与 **`0.1.2-alpha`** 验证。dsh 处于 developer preview,换更新的 dsh 之前先看这一行。dsh 0.1.2-alpha 引入的浏览器认证完全在电脑侧处理,手机 App 无需更新。
|
|
110
112
|
|
|
111
113
|
## 验证过什么
|
|
112
114
|
|
package/index.js
CHANGED
|
@@ -175,6 +175,44 @@ function apply(ctx, config = {}) {
|
|
|
175
175
|
|
|
176
176
|
ctx.effect(() => ctx.webServer.tapIndex(injectNarrowScreenCss))
|
|
177
177
|
|
|
178
|
+
// dsh 0.1.2-alpha 起浏览器界面要求认证:进程启动 token 经 GET /?token= 换成
|
|
179
|
+
// HMAC 签名 cookie,index 与 /api 无 cookie 一律 401。cookie 是 SameSite=Strict
|
|
180
|
+
// 且绑定 Host authority——手机 WebView 的 iframe 属跨站上下文,cookie 根本不会
|
|
181
|
+
// 随请求发出,把 token 交给手机没有用;唯一可行位置在电脑侧:这里自己完成兑换,
|
|
182
|
+
// 把 cookie 交给 sidecar 在代理流上逐请求注入。
|
|
183
|
+
ctx.inject(['connection'], (connCtx) => {
|
|
184
|
+
// rc.7/rc.8 也有 connection 服务,只是没有浏览器认证;判据必须是能力
|
|
185
|
+
// 本身而不是服务存在性(实测 rc.8 走到这里,靠服务存在性判会误报错)
|
|
186
|
+
if (typeof connCtx.connection.authenticatedUrl !== 'function') return
|
|
187
|
+
const authority = new URL(`http://${proxyTarget}`).host
|
|
188
|
+
const exchange = async () => {
|
|
189
|
+
const url = connCtx.connection.authenticatedUrl(`http://${proxyTarget}/`)
|
|
190
|
+
const res = await fetch(url, { redirect: 'manual' })
|
|
191
|
+
const setCookie = res.headers.getSetCookie()
|
|
192
|
+
if (res.status !== 303 || setCookie.length !== 1) {
|
|
193
|
+
throw new Error(`token 兑换应答异常: HTTP ${res.status}, set-cookie ×${setCookie.length}`)
|
|
194
|
+
}
|
|
195
|
+
send({ type: 'proxy-auth', cookie: setCookie[0].split(';', 1)[0], authority })
|
|
196
|
+
}
|
|
197
|
+
const exchangeWithRetry = async () => {
|
|
198
|
+
for (let attempt = 1; ; attempt++) {
|
|
199
|
+
try {
|
|
200
|
+
return await exchange()
|
|
201
|
+
} catch (error) {
|
|
202
|
+
if (attempt >= 3) {
|
|
203
|
+
console.error('[tether] 浏览器认证 cookie 获取失败,手机端将收到 401:', error)
|
|
204
|
+
return
|
|
205
|
+
}
|
|
206
|
+
await new Promise((resolve) => setTimeout(resolve, 1000 * attempt))
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
void exchangeWithRetry()
|
|
211
|
+
// cookie 绝对有效期默认 30 天,dsh 进程可能活得更久;定期重兑换续上
|
|
212
|
+
const timer = setInterval(() => { void exchangeWithRetry() }, 12 * 60 * 60 * 1000)
|
|
213
|
+
connCtx.effect(() => () => clearInterval(timer))
|
|
214
|
+
})
|
|
215
|
+
|
|
178
216
|
// 「打开配置文件」在宿主机桌面开编辑器,手机上按了毫无反应。这条路由把同一份
|
|
179
217
|
// 文件的内容原样交给手机自己渲染。路径由 Host 侧的 settings.documentPath 决定,
|
|
180
218
|
// 不接受客户端传路径——否则就成了任意文件读取。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-tether",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
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 with no server in between (iroh)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
|
@@ -42,18 +42,18 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"@deepseek-ai/dsh-host-webserver": ">=0.1.0-rc.7",
|
|
46
|
-
"@deepseek-ai/dsh-user-approval": ">=0.1.0-rc.7"
|
|
45
|
+
"@deepseek-ai/dsh-host-webserver": ">=0.1.0-rc.7 <0.1.1-0 || >=0.1.2-alpha.0 <0.1.3-0",
|
|
46
|
+
"@deepseek-ai/dsh-user-approval": ">=0.1.0-rc.7 <0.1.1-0 || >=0.1.2-alpha.0 <0.1.3-0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependenciesMeta": {
|
|
49
49
|
"@deepseek-ai/dsh-host-webserver": { "optional": true },
|
|
50
50
|
"@deepseek-ai/dsh-user-approval": { "optional": true }
|
|
51
51
|
},
|
|
52
52
|
"optionalDependencies": {
|
|
53
|
-
"dsh-tether-host-darwin-arm64": "0.1.
|
|
54
|
-
"dsh-tether-host-darwin-x64": "0.1.
|
|
55
|
-
"dsh-tether-host-linux-arm64": "0.1.
|
|
56
|
-
"dsh-tether-host-linux-x64": "0.1.
|
|
57
|
-
"dsh-tether-host-win32-x64": "0.1.
|
|
53
|
+
"dsh-tether-host-darwin-arm64": "0.1.9",
|
|
54
|
+
"dsh-tether-host-darwin-x64": "0.1.9",
|
|
55
|
+
"dsh-tether-host-linux-arm64": "0.1.9",
|
|
56
|
+
"dsh-tether-host-linux-x64": "0.1.9",
|
|
57
|
+
"dsh-tether-host-win32-x64": "0.1.9"
|
|
58
58
|
}
|
|
59
59
|
}
|