dsh-mini-remote 0.1.0 → 0.1.3
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 +65 -0
- package/README.en.md +154 -0
- package/README.md +75 -59
- package/client/client.js +144 -1
- package/lib/browse.js +216 -0
- package/lib/commands.js +166 -0
- package/lib/history.js +72 -0
- package/lib/index.js +644 -5
- package/lib/log-tail.js +235 -0
- package/lib/page.html +1488 -24
- package/lib/page.js +21 -0
- package/lib/pairing.js +103 -14
- package/lib/permissions.js +165 -0
- package/lib/serve.js +358 -0
- package/lib/server.js +429 -6
- package/lib/store.js +134 -2
- package/lib/sw.js +39 -0
- package/lib/tree.js +145 -3
- package/package.json +6 -5
- package/README.zh.md +0 -138
- package/client/verify.mjs +0 -514
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,68 @@
|
|
|
2
2
|
|
|
3
3
|
本文件记录每个版本改了什么。格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
|
4
4
|
|
|
5
|
+
## [0.1.3] - 2026-09-25
|
|
6
|
+
|
|
7
|
+
### 新加的
|
|
8
|
+
|
|
9
|
+
- **手机上也能用 `/` 指令了。** 在输入框里打一个 `/`,输入框上方就会列出这个会话能用的指令(名字 + 一句说明),继续打字按名字过滤,点一下就执行;需要参数的指令会把它填进输入框、并把「它要什么」挂在提示位置,你补完再发。指令跑出来的结果在聊天里单独一行,和 AI 说的话、你自己说的话都长得不一样。**这份名单是 DSH 自己的账本**,不是插件的——电脑上新装一个带指令的插件,手机上刷新就有了。本机这台电脑当前有 6 条:`compact`、`export`、`feedback`、`goal`、`permission`、`plan`。
|
|
10
|
+
- 打错的指令、不存在的指令:**拒绝并说明**(和电脑端同一条规则),不会退回去当成一次提问发给模型。`/model`、`/file` 会特别说一句「这是电脑网页端专有的」——它们确实只活在浏览器那半边,宿主账本里没有。
|
|
11
|
+
- 会话没在跑(睡在硬盘上)时没有指令可列:这时如实说「这个会话现在没在跑,指令要先让它跑起来」,**不显示成一个空名单**(那等于说「一条指令都没有」,是另一回事)。
|
|
12
|
+
- 指令执行会写进会话记录(`command/run` + `command/done` 两条日志事件),所以点开一个老会话时,之前执行过的指令和结果也在——手机上看到的和电脑上是同一份账。
|
|
13
|
+
- **指令这一版带不了附件**:DSH 的指令要的附件凭据和手机上传那套不通。输入框里贴着的附件会**原样留着**(不会被悄悄丢掉),跟下一条普通消息一起发出去。
|
|
14
|
+
|
|
15
|
+
### 修好的
|
|
16
|
+
|
|
17
|
+
- **指令跑完时手机上可能一直挂着「执行中…」(最多一分钟)。** 起因是手机一分钟会重读一次会话日志,如果读的那一刻指令还在跑,记录里那条就写着「执行中」;而它和内存里那条(已经拿到结果)时间戳相同,按原来的合成规则接不上去,于是内存里那份更准的反而没显示出来。现在指令行按 `commandId` 认人,记录里那条就地把结果换成内存这份的。配了一条反向验证(把修复去掉,那条用例确实变红)。
|
|
18
|
+
|
|
19
|
+
## [0.1.2] - 2026-09-25
|
|
20
|
+
|
|
21
|
+
### 新加的
|
|
22
|
+
|
|
23
|
+
- **手机点开一个会话,就能看到它之前每一轮。** 在这之前,手机上只有「插件亲眼看过」的内容:内存里那份历史从 DSH 启动、或者从手机开始遥控的那一刻才开始记,所以一个早就存在的会话点进去是空的。现在点开会话(以及在手机上刷新页面、切换会话)时,插件会去读那个会话的记录,把每一轮的用户指令和最终结论列出来;单帧模式仍然只显示最后一条结论。读不出来(老格式日志、写了一半的日志)就退回手里那份并记一条日志,**不编内容**。
|
|
24
|
+
- 重放和实时走的是**同一套判断**:`lib/history.js` 调的就是 `events.js` 里那个提取器(`createTurnTracker`),两条路的「哪条才算回答」不会走散。
|
|
25
|
+
- 读完就广播一份新快照。手机上看到的顺序是「先有手里那份,再自然补全」,不会空白等待。
|
|
26
|
+
- 顺手修掉了 `tools/peek-events.mjs` 的两个真 bug:多帧 zstd 日志只解第一帧(26MB 的日志只读出 196 字节,看着像「这个会话没内容」)、文件名写死 `session.v3.jsonl.zstd`(v4 的会话根本找不到)。它现在直接用 `lib/log-tail.js` 的帧扫描和文件查找。
|
|
27
|
+
|
|
28
|
+
### 修好的
|
|
29
|
+
|
|
30
|
+
- **开机预热历史撞上「巨型父会话」会把 DSH 本体 OOM 打挂。** 绑定会话如果是**带大量子会话的父会话**(本机实测:310 个子会话、26MB 压缩日志),`sessionQuery.readSession()` 会触发 v3→v4 迁移并把这个父会话的**每个子会话整份解码**,默认约 4GB 堆 20 秒就没了。现在预热前先量规模(`lib/tree.js` 的 `sessionScale`:用已缓存的 `listSessions()` 记录数子会话 + 只 stat 自己的日志体积),超过 `HISTORY_MAX_CHILDREN = 20` 或 `HISTORY_MAX_BYTES = 8MB` 就**不走整份读,改走下面那条有上限的尾部读**(日志里记一条「规模上限:… 改走尾部读」,带上子会话数与日志体积);`pending` 标记仍是**同步**打上,手机侧「正在读」的语义不变。
|
|
31
|
+
- 为什么非要挡在调用之前:`readSession` 一旦被调用,代价发生在 DSH 内核里(迁移 → 全解子会话 + 两次全量克隆),事后省不回来。
|
|
32
|
+
- 实测:绑回那个 310 子会话的父会话,堆峰 521MB(改之前 4364MB → OOM);`npm test` 458/458。
|
|
33
|
+
|
|
34
|
+
### 改了的
|
|
35
|
+
|
|
36
|
+
- **手机端读会话历史有了上限(用户 2026-09-25 的要求:读历史要设上限)。** 三层都是常量、都跟会话总量无关:
|
|
37
|
+
① **读取窗口** `lib/log-tail.js`(新)——只解日志**尾部**若干 zstd 帧:`HISTORY_TAIL_WINDOW_BYTES = 16MB`、`HISTORY_TAIL_MAX_EVENTS = 20000`;窗里一个完整帧都没有(最后一帧比窗口大)时会**放大窗口重来**(4×,上限 64MB),不是直接认输。
|
|
38
|
+
② **展示条数** `HISTORY_MAX_ENTRIES = 200`——重放成聊天记录后只留尾部这么多。
|
|
39
|
+
③ **诚实标注**:`store.snapshot()` 多出 `historyTruncated` / `historyNote`,手机端在聊天内容**最上面**垫一行「这个会话很大,只显示了最近 N 条(读取上限:…)」——条数被砍了却不说,用户会以为这个会话就这么点。
|
|
40
|
+
- 判定:会话「大」(子会话 > 20 或日志 > 8MB)走有上限的尾部读;「小」仍走内核的完整读(日志权威、会话活着还免读盘)。窗口把整份都盖住时**不谎报**截断。
|
|
41
|
+
- 实测(本机最坏那条 26MB / 2.2 万事件的父会话):4MB 窗口→29 条 / 121ms;8MB→87 条 / 203ms;16MB→197 条 / 472ms;32MB(等于整份)→251 条 / 764ms / 堆峰约 540MB。同一份日志走内核 `readSession` 是 4GB 堆 OOM,所以尾部读的代价小两个数量级。
|
|
42
|
+
- 验收:把绑定会话设成那个巨型父会话,`dsh web` 起来堆峰 477MB(不再 OOM),手机 `/mini/api/state` 拿到 **197 条真实历史 + `historyTruncated: true` + 说明文案**;`npm test` **458/458**(新增 `test/log-tail.test.mjs` 8 条、`test/page.test.mjs` 2 条)。
|
|
43
|
+
|
|
44
|
+
## [0.1.1] - 2026-09-25
|
|
45
|
+
|
|
46
|
+
### 新加的
|
|
47
|
+
|
|
48
|
+
- **手机上能回答 AI 的提问了。** 电脑那边的 AI 问你「选哪个」(比如让你挑一个方案)时,问题会推到手机上,点一下就算答了。一个一个答,答错了能回头改,选项里没有的也能自己打字。手机上要是没人(锁屏、关了页面、断了网),问题会自动还给电脑,那边照常弹窗——不会两头都答不上。
|
|
49
|
+
- **权限档位能在手机上切。** 仅可查看 / 工作区内修改 / 完全权限,不用再回电脑改,档位显示中文名。
|
|
50
|
+
- **每个会话的模型和思考强度能在手机上换。** 顶栏那一行就是当前用的模型,点它就能改。会话没在跑(睡在硬盘上)的时候也读得出它上次用的是什么,不用先跑一轮。
|
|
51
|
+
- **手机上能新建工作区和会话。** 浏览电脑上的目录,挑一个登记成工作区,再在里面开会话。
|
|
52
|
+
- **Tailscale 那条路上多了一个加密地址**(形如 `https://你的电脑名.你的网络名.ts.net/`)。它和原来那条是同一台电脑、同一条通道,区别只在连接加不加密。加密之后浏览器才肯给用系统通知和麦克风——要那两样,前提是「加密连接」。
|
|
53
|
+
|
|
54
|
+
### 修好的
|
|
55
|
+
|
|
56
|
+
- Tailscale 那条路:找不到命令时会把该装什么说清楚,检查状态不再让用户干等十五秒;加密地址那条的存在和前提也补上了说明。
|
|
57
|
+
- 开启通知的引导:HarmonyOS 上不再让用户去点一个不存在的东西;权限被拒过之后,会告诉用户「清数据」这条路。
|
|
58
|
+
- 「单帧」和「聊天」两种模式里,新回答落下来时的滚动位置都不再停在末尾。
|
|
59
|
+
- 文案:「锁屏也能提醒」改成「页面在后台时提醒」——它做不到锁屏提醒,原来那句话承诺过头了。
|
|
60
|
+
|
|
61
|
+
### 已知的取舍
|
|
62
|
+
|
|
63
|
+
- 只有 Tailscale 的加密地址和公网隧道是 `https://`。明文那条路上,浏览器不给用系统通知和麦克风。
|
|
64
|
+
- 手机上答的是 AI 主动提给你的选择题。**系统层面的确认弹窗(比如危险命令的审批)手机上点不了**,还得回电脑。
|
|
65
|
+
- 公网隧道的地址每次重启都会换。
|
|
66
|
+
|
|
5
67
|
## [0.1.0] - 2026-09-22
|
|
6
68
|
|
|
7
69
|
第一个版本。
|
|
@@ -25,3 +87,6 @@
|
|
|
25
87
|
- 不做桌面镜像。手机上看不到会话列表、文件树、工具调用详情——这是设计目标,不是还没做。
|
|
26
88
|
|
|
27
89
|
[0.1.0]: https://github.com/xingzhen199186/dsh-mini-remote/releases/tag/v0.1.0
|
|
90
|
+
[0.1.1]: https://github.com/xingzhen199186/dsh-mini-remote/releases/tag/v0.1.1
|
|
91
|
+
[0.1.2]: https://github.com/xingzhen199186/dsh-mini-remote/releases/tag/v0.1.2
|
|
92
|
+
[0.1.3]: https://github.com/xingzhen199186/dsh-mini-remote/releases/tag/v0.1.3
|
package/README.en.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# dsh-mini-remote
|
|
2
|
+
|
|
3
|
+
> A [DeepSeek Harness](https://github.com/deepseek-ai/DeepSeek-Harness) (DSH) plugin that puts a **minimal remote control** on your mobile device — only the instruction you send and the AI's final conclusion reach it. Tool calls, file reads and writes, sub-agent dispatch, and reasoning traces all stay on the computer.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
[中文说明 →](README.md)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Why I built this plugin
|
|
13
|
+
|
|
14
|
+
The idea came from this: an agent task often takes a long time to finish, and if you step out, you need the phone to drive it remotely.
|
|
15
|
+
|
|
16
|
+
But the phone clients that exist show the PC's execution steps in faithful detail. You send one instruction; it may think for several minutes, read dozens of files, call tools a few times, and only then give you a conclusion. If you're out, or busy away from the computer, you simply don't have the time to watch the phone that closely.
|
|
17
|
+
|
|
18
|
+
I don't think that approach is bad. It's complete and controllable, and if you're going to do serious work, it's the right one.
|
|
19
|
+
|
|
20
|
+
But when I'm out, what I want is something else — **a lighter way to interact that asks less of my attention**. The phone screen is small, and so is the attention I have to spare when I'm out. Most of the time I only need one thing: **this round is done, time to send the next instruction.** And even at my desk, I rarely read the AI's running commentary while it works.
|
|
21
|
+
|
|
22
|
+
So the interface here is deliberately crude: it drops the PC's execution steps entirely and puts only the AI's final conclusion in front of you.
|
|
23
|
+
|
|
24
|
+
**In a sense, it exists so that you look at it less.**
|
|
25
|
+
|
|
26
|
+
So you can spend your time more freely — instead of being stuck in that small screen while you're playing with your daughter or out on a trip.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```powershell
|
|
33
|
+
dsh plugin --profile web add dsh-mini-remote
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Or straight from GitHub, if you would rather pin the source:
|
|
37
|
+
|
|
38
|
+
```powershell
|
|
39
|
+
dsh plugin --profile web add github:xingzhen199186/dsh-mini-remote
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
If you already have the source on disk, you can point it at the folder:
|
|
43
|
+
|
|
44
|
+
```powershell
|
|
45
|
+
dsh plugin --profile web add <the folder you put the source in>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**You must restart DSH once after installing**, or nothing new shows up in the settings page. After the restart a "Phone Remote" entry appears in the left column, and the startup log prints the phone URL and password.
|
|
49
|
+
|
|
50
|
+
**Which DSH versions it fits.** This plugin was developed on DSH **0.1.5-rc.2** and re-checked item by item on **0.1.7-rc.2** (every interface it uses was unchanged); **versions below 0.1.5 have not been tried**. `rc` is the tag the project puts on preview builds, and DSH as a whole is still a developer preview — minor versions may break things, so versions newer than 0.1.7 are not guaranteed either. If it ever does hit an incompatibility, the usual symptom is one entry point going missing (the model line at the top, say) while everything else keeps working: the plugin is written so that a missing service switches off that one feature rather than the whole thing.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Configuration: three routes, pick what you need
|
|
55
|
+
|
|
56
|
+
All three connection methods **exist at the same time**. Pick one, or leave several on.
|
|
57
|
+
|
|
58
|
+
Open DSH settings (bottom of the sidebar) → "Phone Remote" in the left column. Every route on that page has a QR code and a link, and the small text under each QR code says **when to use that route**. That's all you need to read.
|
|
59
|
+
|
|
60
|
+
### 1. LAN: at home only
|
|
61
|
+
|
|
62
|
+
When the phone and the computer are on the same Wi-Fi, scan the "LAN" code and you're in. **Nothing extra to install** — the least fuss of the three.
|
|
63
|
+
|
|
64
|
+
The cost is that it stops working the moment you leave: the phone switches to mobile data and this route is gone.
|
|
65
|
+
|
|
66
|
+
### 2. Tailscale: works outside, and the address stays fixed
|
|
67
|
+
|
|
68
|
+
Install [Tailscale](https://tailscale.com) on both the computer and the phone, sign in to the same account, and this route appears on the pairing page by itself. The address is fixed — set it up once and forget it.
|
|
69
|
+
|
|
70
|
+
The cost is an app on each side. If you don't mind installing it, **this is the steadiest route when you're out**.
|
|
71
|
+
|
|
72
|
+
You can take this route one step further and get an encrypted address as well (shaped like `https://your-machine.your-tailnet.ts.net/`). It is **the same computer over the same tunnel** as the entry above; the only difference is that the connection is encrypted. It is not a fourth route — the plain `http://` entry keeps working and keeps showing.
|
|
73
|
+
|
|
74
|
+
Encryption is what makes the browser willing to hand over system notifications, the microphone, and full clipboard access. **Those three need an encrypted connection — they do not specifically need Tailscale**: the public tunnel in route 3 below also gives you an `https://` address, and that is enough.
|
|
75
|
+
|
|
76
|
+
The two encrypted routes have different prerequisites, so it's worth being precise. This one uses a name shaped like `your-machine.your-tailnet.ts.net`, and **that name only resolves inside your Tailscale network**, via MagicDNS on the phone's client. **But some clients don't have that capability** — MeshArc, the third-party client for HarmonyOS, states in its own README that MagicDNS is not enabled and you should use Tailscale IP addresses; on such a phone this encrypted route simply won't work, and it isn't a matter of a setting being switched off. The tunnel route uses a Cloudflare name that resolves for anyone and doesn't care about the phone; its cost is that the address changes on every restart.
|
|
77
|
+
|
|
78
|
+
There's a switch on the pairing page — just turn it on. The first time, you have to confirm it in Tailscale's admin console: it is a tailnet-wide switch, and the plugin cannot click it for you. So the pairing page puts the exact link Tailscale hands out right in front of you — one click and you're there. If this computer isn't signed in to Tailscale yet, it says so and gives you a sign-in link instead.
|
|
79
|
+
|
|
80
|
+
### 3. Public access: nothing to install
|
|
81
|
+
|
|
82
|
+
There's a switch at the bottom of the pairing page. Turn it on and Cloudflare hands you a public URL (shaped like `https://random-words.trycloudflare.com/`). The phone can reach it on any network, **with nothing installed**. It is an **encrypted connection**, so the three browser capabilities (system notifications, microphone, clipboard) work on this route too — if the phone's Tailscale DNS setting can't be turned on, this is how you still get encryption.
|
|
83
|
+
|
|
84
|
+
Two costs, worth knowing before you decide:
|
|
85
|
+
|
|
86
|
+
- **The address changes every time you restart DSH.** When it does, come back and scan the new code.
|
|
87
|
+
- **The first time is slow** — it's downloading a component of about 50 MB, and only that once. While it does, the status line reads "opening…", which is normal, not a hang. Registration occasionally fails; the plugin retries three times on its own.
|
|
88
|
+
|
|
89
|
+
Once it's on, **wait half a minute before scanning.** Cloudflare needs a moment to publish the address. Scanning too early reports that it can't be opened — that's not breakage, it's just too soon.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
<img width="1314" height="2186" alt="screenshot_20260922_233535_com huawei hmos brows" src="https://github.com/user-attachments/assets/8befa186-3e20-4c0e-8efc-8ea523f77648" />
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
## What the mobile side does
|
|
97
|
+
|
|
98
|
+
Open the link and that's the whole interface: one input box, and the latest reply.
|
|
99
|
+
|
|
100
|
+
**Send instructions.** Type and send; the AI starts working on the computer.
|
|
101
|
+
|
|
102
|
+
**Wait for the conclusion.** While it runs, the page shows "running…". You can keep sending during that time — instructions queue up. When the task ends, the conclusion appears on the page, and the phone chimes and buzzes.
|
|
103
|
+
|
|
104
|
+
**Two display modes.** Tap the ⚙ in the top right to switch. "Single frame" (the default) keeps only the newest reply on screen — good for "I just want to see how this one turned out". "Chat" is a back-and-forth bubble list — good for several rounds of follow-up questions. Use it for a while and you'll know which you prefer.
|
|
105
|
+
|
|
106
|
+
**Open a session and you see what was said in it before.** Switch to a session that has existed for a while and Chat mode lists every earlier round (the instructions you sent, the conclusion of each round); Single frame shows only the last conclusion. **Very large sessions show only the most recent stretch**: reading one of those in full — tens of thousands of events — would drag the DSH process on your computer down, so the plugin reads just the tail and says so at the top ("this is not everything, only the most recent stretch"). That line is not boilerplate; it is the truth.
|
|
107
|
+
|
|
108
|
+
**Slash commands work from the phone too.** Type a `/` in the input box and the commands available in this session appear above it; keep typing to filter by name, tap one to run it, and commands that take arguments get filled in for you along with a note on what they expect. The list is DSH's own on your computer (whatever plugins are installed), and a command's result gets its own row in the chat, visually distinct from what the AI said. A mistyped or unknown command is refused with an explanation — it is **not** sent as a message. When the session is not running there are no commands to list, and the page says so. **Commands cannot carry attachments** in this version: files you have attached stay put and go out with your next ordinary message.
|
|
109
|
+
|
|
110
|
+
**Answer questions from the phone.** When the AI asks you to pick something (choose one of several plans, say), the question is pushed to the phone and a tap answers it — **one at a time, revisable if you change your mind, and you can type your own answer** when none of the options fit. If nobody is at the phone (locked, page closed, network gone), the question goes straight back to the computer and the dialog pops up there as usual.
|
|
111
|
+
|
|
112
|
+
**Three things you can change in passing.** Tap the line at the top to switch the current session's model and reasoning effort; switch the permission preset (View Only / Workspace Write / Full Access); browse the computer's folders to register a new workspace and start a session in it.
|
|
113
|
+
|
|
114
|
+
**You're reading conclusions, not the process.** There's no tool-call chain and no file diff on the page. **System-level confirmation dialogs cannot be answered from the phone** (approving a dangerous command, for instance) — those still need the computer. What the phone can answer is the multiple-choice question the AI puts to you; the two are not the same thing. It's a remote control: the TV still has to be on for the remote to be any use.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## FAQ
|
|
119
|
+
|
|
120
|
+
**The QR code scans but the page won't open.**
|
|
121
|
+
First check that the phone and the computer are on the same Wi-Fi.
|
|
122
|
+
|
|
123
|
+
**Scanning the "public" route from outside won't open.**
|
|
124
|
+
Wait half a minute and try again. If it still won't, the pairing page shows the reason directly. The most common one is **a proxy or VPN running on the computer** — the "TUN mode" in tools like Clash cuts the tunnel's connections; the process looks fine while not a single connection has actually been established. Turn it off and try again. Another possibility: that network simply can't reach Cloudflare (it's intermittent in mainland China, and not something you misconfigured). If so, don't burn time on the public route — **switch to the Tailscale route**.
|
|
125
|
+
|
|
126
|
+
**It says "disconnected".**
|
|
127
|
+
This happens often after the phone has been in the background. The page reconnects by itself; give it a few seconds. If that doesn't work, open settings and tap "Reconnect".
|
|
128
|
+
|
|
129
|
+
**The reply arrives but there's no sound.**
|
|
130
|
+
Audio only plays after you've touched the page once. Tap it.
|
|
131
|
+
|
|
132
|
+
**The phone keeps asking for a password.**
|
|
133
|
+
That means the link you opened didn't carry one — for example, you typed the address by hand. Go back to the computer and scan the QR code again.
|
|
134
|
+
|
|
135
|
+
**I want a password I can remember.**
|
|
136
|
+
Change it in the password section of "Settings → Phone Remote". **At least 12 characters.** A DSH restart is required afterwards, and the phone has to scan a new code.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Security
|
|
141
|
+
|
|
142
|
+
**The pairing page carries the password — don't screenshot it and send it around.** The password is encoded straight into the QR code so you never have to type it. That's convenient, and the price is that whoever holds that image can get in.
|
|
143
|
+
|
|
144
|
+
Beyond that: every endpoint requires the password; password comparison is constant-time; five wrong attempts from one source blocks that source for a minute; pairing information is **readable only from the local machine**, so other devices on the same Wi-Fi can't get it; the public tunnel is off by default and you have to turn it on yourself in the settings page; the phone sees no file contents — when you pick a workspace it lists folder names only, and never lists or reads files. **One thing worth stating plainly: the phone can switch the agent's permission preset.** On Full Access, the agent can then modify any file on this computer. That path is open.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Credits
|
|
149
|
+
|
|
150
|
+
This plugin's design draws on [dsh-pocket](https://www.npmjs.com/package/dsh-pocket) by shaobeichen — in particular the shape of the configuration page, where each connection route gets its own link, its own QR code, and its own password.
|
|
151
|
+
|
|
152
|
+
## License
|
|
153
|
+
|
|
154
|
+
MIT
|
package/README.md
CHANGED
|
@@ -1,138 +1,154 @@
|
|
|
1
1
|
# dsh-mini-remote
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 一个 [DeepSeek Harness](https://github.com/deepseek-ai/DeepSeek-Harness)(DSH)插件,把一部手机变成**极简遥控器**——移动端只收到你发出去的指令和 AI 最后的结论,工具调用、文件读写、子 Agent 调度、思考过程全部留在电脑上。
|
|
4
4
|
|
|
5
5
|

|
|
6
6
|

|
|
7
7
|
|
|
8
|
-
[
|
|
9
|
-
|
|
10
|
-
**To use this plugin from your phone, switch the DSH session page on your PC to Full Access(完全权限)** — approvals cannot be granted from the phone, so a session waiting on one will simply stall.
|
|
8
|
+
[English →](README.en.md)
|
|
11
9
|
|
|
12
10
|
---
|
|
13
11
|
|
|
14
|
-
##
|
|
12
|
+
## 为什么做这个插件
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
初衷是因为现在AGENT任务执行一轮往往需要很久,而如果出门,则需要手机端来远程操作。
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
但现有的手机端,会把PC的执行步骤非常还原地展现出来。你发一条指令,它可能要想上几分钟、读几十个文件、调好几次工具,最后才给你一个结论。如果出门或有事不在电脑前,实在没时间盯着手机看那么细致。
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
我并不认为那种方式不好。信息完整、过程可控,如果你要认真处理任务,它是对的。
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
但出门在外的时候,就我个人而言,我需要的是另一种东西——**更轻便、更少占用注意力的交互方式**。手机屏幕就那么大,出门时的精力也就那么多。而大部分时候我真正需要的只有一件事:**这一轮跑完了,该发下一条指令了**。而且大部分时间,即使在电脑上,我也很少会去仔细阅读AI做执行过程中的“自言自语”。
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
所以这个插件的界面做得相当「原始」:它完全省略了电脑网页端的执行步骤,只把 AI 最后的结论送到你面前。
|
|
25
23
|
|
|
26
|
-
|
|
24
|
+
**某种意义上,它的存在,是为了让你更少地去看它。**
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
你可以更加自由地支配自己的时间,而不是当你和女儿玩耍时,抑或出游时,被困在那个小小的屏幕里。
|
|
29
27
|
|
|
30
28
|
---
|
|
31
29
|
|
|
32
|
-
##
|
|
30
|
+
## 安装
|
|
33
31
|
|
|
34
32
|
```powershell
|
|
35
|
-
dsh plugin --profile web add
|
|
33
|
+
dsh plugin --profile web add dsh-mini-remote
|
|
36
34
|
```
|
|
37
35
|
|
|
38
|
-
|
|
36
|
+
也可以直接从 GitHub 装,这样锁的是源码:
|
|
39
37
|
|
|
40
38
|
```powershell
|
|
41
|
-
dsh plugin --profile web add dsh-mini-remote
|
|
39
|
+
dsh plugin --profile web add github:xingzhen199186/dsh-mini-remote
|
|
42
40
|
```
|
|
43
41
|
|
|
44
|
-
|
|
42
|
+
手上有源码目录的话,把目录指给它也一样:
|
|
45
43
|
|
|
46
44
|
```powershell
|
|
47
|
-
dsh plugin --profile web add
|
|
45
|
+
dsh plugin --profile web add <你放源码的目录>
|
|
48
46
|
```
|
|
49
47
|
|
|
50
|
-
|
|
48
|
+
装完**必须重启一次 DSH**,设置页里才会出现新东西。重启后左栏会多出「手机遥控」,启动日志里也会打印手机访问地址和密码。
|
|
49
|
+
|
|
50
|
+
**它适配哪些 DSH 版本。** 这个插件在 DSH **0.1.5-rc.2** 上开发,在 **0.1.7-rc.2** 上重新逐项核对过(插件用到的那些接口,一个都没变),**低于 0.1.5 的版本没试过**。`rc` 是官方给预览版编的号,DSH 目前整体还是开发者预览版,跨小版本可能有破坏性改动,所以比 0.1.7 更新的版本同样不保证。真遇上不兼容,症状一般是某一块入口不见了(比如顶栏那行模型),其余部分照常——插件是按「少了哪个服务就关掉哪块功能」写的,不会整个起不来。
|
|
51
51
|
|
|
52
52
|
---
|
|
53
53
|
|
|
54
|
-
##
|
|
54
|
+
## 配置:三条路,按需要选
|
|
55
|
+
|
|
56
|
+
三条连接方式**同时存在**,选一条就行,也可以都开着。
|
|
55
57
|
|
|
56
|
-
|
|
58
|
+
打开 DSH 设置(侧边栏最下面)→ 左栏「手机遥控」。这一页上每条路都有一个二维码和一条链接,二维码底下那行小字写着**什么时候用这条**,看它就够了。
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
### 一、内网:只在家里用
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
手机和电脑连同一个 Wi-Fi 时,扫「内网」那个码就能用。**不需要任何额外安装**,最省事的一条。
|
|
61
63
|
|
|
62
|
-
|
|
64
|
+
代价是出了门就连不上——手机一切到流量,这条就断了。
|
|
63
65
|
|
|
64
|
-
|
|
66
|
+
### 二、Tailscale:出门也能连,地址还固定
|
|
65
67
|
|
|
66
|
-
|
|
68
|
+
电脑和手机都装上 [Tailscale](https://tailscale.com)、登录同一个账号,配对页上就会自动多出这一条。地址固定,配一次以后不用再管。
|
|
67
69
|
|
|
68
|
-
|
|
70
|
+
代价是两边都要装一个 App。如果你不介意装,**出门在外这条最稳**。
|
|
69
71
|
|
|
70
|
-
|
|
72
|
+
这条路上还能再开一步,多拿一个加密地址(形如 `https://你的电脑名.你的网络名.ts.net/`)。它和上面那条是**同一台电脑、同一条通道**,区别只在连接加不加密——不是第四条路,那条明文的照旧能用、也照旧显示。
|
|
71
73
|
|
|
72
|
-
|
|
74
|
+
加密之后,浏览器才肯给用系统通知、麦克风、剪贴板的完整能力。**要那三样,前提是「加密连接」,不是非得走 Tailscale**——下面第三条的公网隧道给的也是 `https://` 地址,一样够用。
|
|
73
75
|
|
|
74
|
-
|
|
76
|
+
两条加密路各有各的前提,说清楚免得你走错:这一条用的是形如 `你的电脑名.你的网络名.ts.net` 的域名,**它只在你的 Tailscale 网络内部解析得出**,靠的是手机客户端上的 MagicDNS。**但有些客户端没有这个能力**——HarmonyOS 上那个第三方客户端 MeshArc,它自己的说明里就写着「请用 Tailscale IP 地址」,那类手机上这条加密路走不通,不是设置没开的问题。隧道那条用的是 Cloudflare 的域名,谁都能解析,不挑手机,代价是地址每次重启都会换。
|
|
75
77
|
|
|
76
|
-
|
|
78
|
+
配对页上有一个开关,打开就行。第一次开需要你在 Tailscale 的后台确认一次——那是整个网络级别的开关,插件代不了你点,所以配对页会把 Tailscale 给出的那条链接直接摆在你面前,点一下就过去。要是这台电脑还没登录 Tailscale,它会说清楚,并给你登录链接。
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
- **The first time is slow** — it's downloading a component of about 50 MB, and only that once. While it does, the status line reads "opening…", which is normal, not a hang. Registration occasionally fails; the plugin retries three times on its own.
|
|
80
|
+
### 三、公网访问:什么都不用装
|
|
80
81
|
|
|
81
|
-
|
|
82
|
+
配对页最底下有个开关,打开它,Cloudflare 会给你一个公网网址(形如 `https://随机词.trycloudflare.com/`)。手机在任何网络下都能连,**不用装任何东西**。它是**加密连接**,所以浏览器那三样(系统通知、麦克风、剪贴板)在这条路上也够用——手机上 Tailscale 的 DNS 设置开不了的话,想要加密就走这条。
|
|
83
|
+
|
|
84
|
+
两个代价,先知道再决定:
|
|
85
|
+
|
|
86
|
+
- **地址每次重启 DSH 都会换**,换了得回来重新扫一次码。
|
|
87
|
+
- **第一次打开会慢**——它在下载一个五十兆左右的组件,只下这一次。这期间状态那行会显示「正在打开…」,那是正常的,不是卡死。注册偶尔会失败,插件会自动重试 3 次。
|
|
88
|
+
|
|
89
|
+
打开之后**等半分钟再扫**。Cloudflare 需要一点时间把这个地址公布出去,太早扫会提示打不开——那不是坏了,是还没到时候。
|
|
82
90
|
|
|
83
91
|
---
|
|
84
92
|
|
|
85
93
|
<img width="1314" height="2186" alt="screenshot_20260922_233535_com huawei hmos brows" src="https://github.com/user-attachments/assets/8befa186-3e20-4c0e-8efc-8ea523f77648" />
|
|
86
94
|
|
|
87
95
|
|
|
88
|
-
##
|
|
96
|
+
## 移动端能做什么
|
|
97
|
+
|
|
98
|
+
打开链接就是全部界面:一个输入框,和最新的一条回复。
|
|
99
|
+
|
|
100
|
+
**发指令。** 打字发出去,AI 就在电脑上开始干活。
|
|
101
|
+
|
|
102
|
+
**等结论。** 跑的时候上面显示「运行中…」。这期间你可以接着发,指令会排队。任务结束,结论直接出现在页面上,同时响一声、震一下。
|
|
103
|
+
|
|
104
|
+
**两种显示模式。** 点右上角的 ⚙ 切换。「单帧」(默认)整屏只留最新一条回复,适合「我就想看这次的结果」;「聊天」是一来一回的气泡列表,适合连着追问好几轮。用一阵子你会知道自己偏哪个。
|
|
89
105
|
|
|
90
|
-
|
|
106
|
+
**点开一个会话,能看到它之前聊过什么。** 在左边切到一个早就存在的会话,聊天模式会把之前的每一轮都列出来(你发过的指令、每一轮的结论),单帧模式只显示最后一条结论。**特别大的会话只给最近一段**:那种几万个事件的会话,整份读下来会把电脑上的 DSH 拖垮,所以只读末尾那一小段,并在最上面写明「这不是全部,只显示了最近一段」——你看到的那句话不是客套话,是实情。
|
|
91
107
|
|
|
92
|
-
|
|
108
|
+
**斜杠指令也能在手机上用。** 在输入框里打一个 `/`,上面就会列出这个会话能用的指令,接着打字按名字过滤,点一下就执行;要参数的会帮你填好、并告诉你它要什么。名单是电脑上 DSH 自己的那份(装了什么插件就有什么),执行结果在聊天里单独占一行,和 AI 说的话区分得开。打错的、不存在的指令会被明确拒绝并说明原因,**不会当成一句话发出去**。会话没在跑的时候没有指令可列,页面会直说。**指令这一版带不了附件**:你贴着的文件会留着,跟下一条普通消息一起发。
|
|
93
109
|
|
|
94
|
-
|
|
110
|
+
**在手机上答题。** AI 问你「选哪个」(比如让你挑一个方案)时,问题会推到手机上,点一下就算答了——**一个一个答,答错了能回头改,选项里没有的也能自己打字**。手机不在跟前(锁屏、关了页面、断了网)就自动把问题还给电脑,那边照常弹窗。
|
|
95
111
|
|
|
96
|
-
|
|
112
|
+
**顺手能改的三样。** 点顶栏那一行,换当前会话的模型和思考强度;切权限档位(仅可查看 / 工作区内修改 / 完全权限);浏览电脑上的目录,登记新的工作区和会话。
|
|
97
113
|
|
|
98
|
-
|
|
114
|
+
**看的是结论,不是过程。** 页面上没有工具调用链、没有文件 diff。**系统层面的确认弹窗手机上点不了**(比如危险命令的审批),那类还得回电脑处理——手机上能答的是 AI 主动提给你的选择题,这两件事不一样。它的定位是一根遥控器:电视还得在那儿开着,遥控器才有用。
|
|
99
115
|
|
|
100
116
|
---
|
|
101
117
|
|
|
102
|
-
##
|
|
118
|
+
## 常见问题
|
|
103
119
|
|
|
104
|
-
|
|
105
|
-
|
|
120
|
+
**扫码之后打不开。**
|
|
121
|
+
先看手机和电脑是不是同一个 Wi-Fi。
|
|
106
122
|
|
|
107
|
-
|
|
108
|
-
|
|
123
|
+
**出门扫「公网」那条打不开。**
|
|
124
|
+
等半分钟再试。还不行的话,配对页上会直接显示原因。最常见的一种是**电脑上开着代理或 VPN**——Clash 这类软件的「TUN 模式」会把隧道的连接掐断,进程看着好好的,其实一条连接都没建立起来,先把它关掉再试。还有一种:这条网络就是走不通 Cloudflare(国内时好时坏,不是你哪里配错了),那就别在公网上耗着,**改用 Tailscale 那条**。
|
|
109
125
|
|
|
110
|
-
|
|
111
|
-
|
|
126
|
+
**显示「未连接」。**
|
|
127
|
+
手机切后台再回来经常会这样,页面会自己重连,等几秒;还不行就进设置点「重连」。
|
|
112
128
|
|
|
113
|
-
|
|
114
|
-
|
|
129
|
+
**回复到了,但没声音。**
|
|
130
|
+
声音要你先碰过页面才会响,点一下就行。
|
|
115
131
|
|
|
116
|
-
|
|
117
|
-
|
|
132
|
+
**手机上一直让我输密码。**
|
|
133
|
+
说明你打开的链接里没带密码(比如自己手打的地址)。回电脑上重新扫一次二维码就好。
|
|
118
134
|
|
|
119
|
-
|
|
120
|
-
|
|
135
|
+
**想换一个自己记得住的密码。**
|
|
136
|
+
在「设置 → 手机遥控」的密码那一块直接改,**至少 12 位**。改完要重启一次 DSH,重启之后手机上要重新扫一次码。
|
|
121
137
|
|
|
122
138
|
---
|
|
123
139
|
|
|
124
|
-
##
|
|
140
|
+
## 安全
|
|
125
141
|
|
|
126
|
-
|
|
142
|
+
**配对页上带着密码,别截图发出去。** 密码直接编在二维码里,扫完不用手敲——方便是方便,代价是谁拿到这张图谁就能进。
|
|
127
143
|
|
|
128
|
-
|
|
144
|
+
除此之外:所有接口都要密码,密码比对用定长比较;同一来源一分钟错 5 次就挡一分钟;配对信息**只允许本机读取**,同一个 Wi-Fi 下的其他设备拿不到;公网隧道默认关着,要你自己在设置页里打开;手机看不到任何文件内容——挑工作区的时候只列文件夹名字,文件一个都不列、也不读。**但有一件事要说清楚:手机上能切换 Agent 的权限档位。**切到「完全权限」,Agent 就能改这台电脑上的任何文件。这条路径是开着的。
|
|
129
145
|
|
|
130
146
|
---
|
|
131
147
|
|
|
132
|
-
##
|
|
148
|
+
## 致谢
|
|
133
149
|
|
|
134
|
-
|
|
150
|
+
这个插件在设计思路上参考过 [dsh-pocket](https://www.npmjs.com/package/dsh-pocket)(作者 shaobeichen)——尤其是「每条连接路径各配一条链接、一个二维码、一个密码」这种配置形态。
|
|
135
151
|
|
|
136
|
-
##
|
|
152
|
+
## 许可
|
|
137
153
|
|
|
138
154
|
MIT
|