dsh-mini-remote 0.1.9 → 0.2.1

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,73 @@
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.2.1] - 2026-10-17
6
+
7
+ 这一版跨了十天、46 笔改动,主体是**「远程窗口」真的能跨电脑了** —— 在另一台电脑的 DSH 桌面端里,打开这台电脑的界面。它前面压着一件必须先做的事:**多设备身份**(原来一个口令管所有设备,撤销一台等于全撤)。后面跟着一串"让它用起来不别扭"的修补,以及一件拖了很久的工程账:**这个仓库终于有 CI 了**。
8
+
9
+ ### 新加的
10
+
11
+ - **跨电脑「远程窗口」。** 在 B 电脑的 DSH 桌面端里,打开 A 电脑的界面——不用切窗口、不用远程桌面。做法是"一次性票据过门":A 发一张 30 秒、只能兑一次的票,B 的浏览器拿着它进门,进门那一刻换成窗口会话;**访问口令和长期凭据一个字节都不进浏览器**。跨站嵌入默认只许同源,带票那一次才放开。
12
+ - **地址怎么填**:填那台电脑「手机遥控」页里那条,**必须 https**(明文能配对、能取票,但框里是白的——通行凭据在非 https 的地址上会被浏览器丢掉,这是实测出来的)。推荐 Tailscale:地址固定,设一次就好。
13
+ - **A 侧有一个默认关的总开关「允许别的电脑连接」**。关着的时候,配对和取票两条路一条都不接——"关"是一个用户能读懂的整体状态。
14
+
15
+ - **多设备身份。** 每台设备一枚自己的凭据,可以单独撤销(撤销是即时的,连已经开着的窗口下次请求也会 401)。**手机页的地址栏不再带着访问口令**——口令退回它本来的角色:入场邀请函,扫一次码就发一张凭据。
16
+ - 电脑端设置页多了设备列表:看得到谁连过、能改名、能撤销。
17
+
18
+ - **自检。** 设置页最末多了一块,回答三个问题:**这台跑的是哪一版**、**哪些接口现在真的在**、**开关什么状态**。它还会说一句"进程比代码旧"——那是真机上真出过的事:桌面端连开一天,装是新版,跑的却是旧的。
19
+
20
+ - **出错的时候,看得见了。** 原来错误只打在终端里,用户看着图形界面一个字也看不到;跨机那条路连状态都不留,退出面板就再也查不到。现在有一圈"最近 20 条错误"进自检,**进去之前先脱敏**(口令、飞书密钥、地址里的凭据参数、设备凭据形状,四类都换成 `***`)。
21
+
22
+ - **电脑端界面的顶栏改成鼠标碰顶才滑出**,感应带从 6 像素加高到 16(原来几乎要精确放到那条线上)。
23
+
24
+ ### 改了的
25
+
26
+ - **侧栏那枚「远程窗口」点开是「其他电脑」名单,不再显示本机界面。** 人坐在电脑前,为什么还要在面板里再看一遍自己的界面——"看本机"是跨机做不出来时的中间验证,跨机做完了它就退休了。底层那套取票、嵌框、过门的零件保留(跨机在复用)。
27
+ - 手机侧栏的会话条目补齐了执行功能:重命名、置顶、归档、分叉。归档相关的两个按钮先藏起来(代码不删)。
28
+ - 「完整」模式回答落定后,停在这一轮内容的开头,不再停在总结正文的开头。
29
+
30
+ ### 修了的
31
+
32
+ - **远程窗口每约 25 秒整屏重载一次。** 根因是面板自己在定时换票(票一变,框的地址就变)。那个凭据本来就不会按时间过期——它只在 DSH 重启或对面撤销时失效——所以定时换票纯属多余,拆掉。
33
+ - **取票请求没有超时。** 对面不回话时,那一屏会永远停在"正在向那台电脑换一张通行证…"。现在 15 秒上限(比宿主自己那条 8 秒长,不会把"慢但会成"的请求掐掉),超时给一句人话 + 「再试一次」。
34
+ - **那个 20 秒兜底在框加载成功之后不取消**,会在加载好 19 秒后把正常界面换成"一直没打开"。现在框一加载好就掐钟。
35
+ - **框没打开时自动重取一次票。** 上一版拆掉定时换票之后只剩人手动重试,而"第一次加载被拖过 30 秒"本来能救回来——补上这条约束:自动重取永远跟着一次人的动作,最多一次,不会变成每 20 秒自己转。
36
+ - **「再点一下退出远程窗口」失效**:退出入口只挂在 16×16 的图标上,人点的是 252×36 那一行。改成整行都认。
37
+
38
+ ### 工程
39
+
40
+ - **加了 CI(GitHub Actions)。** 两个 job:`gate` 在 Windows 上跑 Node 22 与 24(红了就是真红),`probe` 在 Linux 上跑一遍(允许红,但要看得见——它红一般是"某条测试只在 Windows 上成立")。加载探针、活体检查、真机这三层仍然手跑:它们要活的 DSH,塞进 CI 只会长期红着然后没人看。
41
+ - **版本号与 CHANGELOG 改成互证。** 原来测试里钉着一个字面量版本,发一次版要改三个地方,其中一个纯粹是为了让测试继续绿。现在断言"`package.json` 的 version 必须等于 CHANGELOG 最顶上那条",忘一处必红。
42
+ - **体量守门**:手机页不超过 8,700 行 / 480 KB,发布包不超过 3 MB(问 `npm pack` 要真实数字,不自己遍历目录)。
43
+ - **发版清单入仓**(`docs/发版清单.md`):七步,从改版本到 publish 之后的核对。
44
+ - CI 首跑红了两次,抓到的都是**本机永远发现不了**的问题:一条测试要 `numpy` 而 skip 条件只探了 python;三条测试把时间钉死在 `+08:00`,而界面按本地时区显示(本机是 UTC+8 所以一直绿)。顺带记下一个能在本地预演 CI 的办法:`$env:TZ="UTC"` 之后再跑。
45
+
46
+ ## [0.2.0] - 2026-10-08
47
+
48
+ 这一版跨了三天、50 笔改动,主体是**「进阶设置」——把电脑端那整套界面搬到手机上**,加上一颗「回到底部」的浮标,以及它俩连着带出来的一批手机端修补。
49
+
50
+ ### 新加的
51
+
52
+ - **手机上能看到电脑端那整套界面了。** 手机这张遥控页是专门为手机做的,所以电脑上那些插件贡献的设置页它进不去——改模型配置、装卸插件、翻会话记录这些事,原来只能回电脑。现在设置页多了一项「进阶设置」:打开它,下面多出一行「电脑端界面」,点「打开」,**同一份电脑端页面原样嵌在手机这半边**(不跳转、不开新标签,关掉就真停)。**它默认关着,打开要付代价**:开启等于把这个访问口令的权限,从遥控页露出的那一点扩到**整个电脑端设置面**(模型配置、凭据页、插件装卸、会话记录),所以页面上写明后果,要点两次才算开;服务端拿不到电脑端地址时整行不显示——不摆一个假的开关。
53
+
54
+ - 这四十来笔里绝大多数是把它磨到能用。值得记的是几处根因:**白屏**有两处(挂载前缀不对,加上我们自己多带了一个 token 参数);**「一直正在重新连接」**是 WebSocket 没转发;**一堆 403** 是 WebSocket 握手和普通请求的 `Origin` 得换成上游自己;**界面加载不出来**是镜像前缀下面的 POST 没转;**重启后卡在「Loading plugins」**是宿主还没就绪就被问了,该等而不是立刻回 502;一次 34 MB 的大附件照旧转发;带内容指纹的静态资源补了长期缓存。
55
+
56
+ - **首帧没字**查了好几轮,最后在真面板上量出来真凶:另一个插件贴在根元素上的「卷起」标记(`opacity:0`)。我们把那个标记摘掉,从样式上根治,删掉了中途加的盲兜底。**内容区滚不动**是我们自己的适配漏了一格 `min-height:0`;**侧栏那一列不能滚、「设置」够不着**、**侧栏中间那层被压成 0**(历史会话看不见)、**主页整片空白**、**插件市场那一节被压窄**各有各的根因,都修了;插件市场的「能滚的列表窗口」从 356 做到 498 像素。
57
+
58
+ - **这一页的适配由我们自己来**:别的插件写死了「只在窄屏生效」的样式,一律摘掉(`dsh-pocket` 是真正动官方设置面板的那一个,单独挡在门外)。官方设置面板的导航掰回竖排、字始终显示;插件市场那格的社区介绍、两个用不上的按钮先藏起来,把地方让给要用的东西。
59
+
60
+ - **怎么知道 DSH 一升级、这些适配会不会悄悄失效**:多了一份**结构依赖清单**(`tools/structure-deps.mjs`),把我们靠官方界面上的哪些「标记」活着一条条登记下来,并标明失配的后果(只是这一条不生效,还是可能误伤别处);配一个**升级自检**(`tools/structure-check.mjs`)对着活界面逐条查,中文报告、失配非零退出。清单和代码之间还钉了测试:改了代码没改清单、加了新依赖没登记,都会红。
61
+
62
+ - **多了一颗「回到底部」的圆形浮标。** 照电脑端 DSH 那颗做:聊天和「完整」两个模式里,往上翻过之后右下角浮出来,点一下回到最新那一条。**单帧模式下它一律不出现**(那一模式整屏只有一条回复,没有「回去」这回事);渐出 130 毫秒;深色浅色各适配一套——浅色下那道环深一档、抬一层更轻的投影,深色下投影本来等于零就去掉;看得见的圆比按得到的地方小一档(热区是手指的下限,不该跟着缩)。尺寸和位置是量着调的:看得见的面积先减半(38 → 27)、往左让开滚动条那条带,最后又增大一档到 31。
63
+
64
+ ### 修了的
65
+
66
+ - **「完整」模式里执行轨迹那个「进行中」不再竖着折行**(真机复现过);组头右侧的「模型原话」也走上 markdown 渲染,和别处的正文一个长相。
67
+ - **插话发送真的插话了。** 0.1.9 只做了「繁忙时是排队还是插话」那个开关,没接到发送路径上——选了插话,实际还是排队。
68
+ - **镜像页偶尔显示 `{"error":"not found"}`。** 那是我们自己的兜底 404:进阶设置关着的时候,门后面本来就不该回 JSON。
69
+ - **进阶设置关着时,那一行仍然显示。** 根因在 CSS,不在 JS。
70
+ - **`engines.dsh` 和 `peerDependencies` 声明的是同一个区间了。** 两处不一致时,npm 拿一个、宿主看另一个。
71
+
5
72
  ## [0.1.9] - 2026-10-05
6
73
 
7
74
  这一版跨了三天、74 笔改动,主体是**设置页整屏化与插件页**、**「完整」显示模式与执行轨迹**,以及一串观感与读取速度的修补。
package/README.en.md CHANGED
@@ -1,242 +1,299 @@
1
+ <div align="center">
2
+
1
3
  # Minimal Remote · dsh-mini-remote
2
4
 
3
- [![npm](https://img.shields.io/npm/v/dsh-mini-remote)](https://www.npmjs.com/package/dsh-mini-remote)
4
- ![DSH plugin](https://img.shields.io/badge/DSH_plugin-dsh--plugin-blue)
5
- ![License](https://img.shields.io/badge/license-MIT-green)
5
+ <p align="center">
6
+ <img src="https://raw.githubusercontent.com/xingzhen199186/dsh-mini-remote/main/docs/promo.webp" alt="Minimal Remote: the phone keeps your instruction and its conclusion, and shows you the process only when you ask for it" width="720" />
7
+ </p>
6
8
 
7
- [中文说明](README.md)
9
+ **A lightweight mobile remote plugin crafted for DeepSeek Harness (DSH) users, resolving screen clutter and process fatigue when checking Agent status and dispatching instructions away from the desk.**
8
10
 
9
- ![Minimal Remote: only your instruction and the AI's conclusion reach the phone; everything in between stays on the computer](https://raw.githubusercontent.com/xingzhen199186/dsh-mini-remote/main/docs/promo.webp)
11
+ [![npm](https://img.shields.io/npm/v/dsh-mini-remote)](https://www.npmjs.com/package/dsh-mini-remote)
12
+ [![Node.js](https://img.shields.io/badge/node-%5E22.19.0%20%7C%7C%20%3E%3D24.0.0-brightgreen)](https://nodejs.org/)
13
+ [![DSH](https://img.shields.io/badge/DSH-%3E%3D0.1.5--rc.2%20%3C0.3.0-blue)](https://github.com/deepseek-ai/DeepSeek-Harness)
14
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
10
15
 
11
- **You send one line; the phone gets one conclusion.**
16
+ [English](README.en.md) · [简体中文](README.md)
12
17
 
13
- Tool calls, file reads and writes, sub-agent dispatch, and the body of the reasoning trace never reach the phone. This plugin exists for one situation: you're out, and all you want to do is send an instruction and read the result — a phone, one input box, the latest reply.
18
+ </div>
14
19
 
15
- [What it is](#what-it-is) ・ [When you'd use it](#when-youd-use-it) ・ [Install](#install) ・ [Connecting your phone](#connecting-your-phone-three-routes-pick-one) ・ [What the phone can do](#what-the-phone-can-do) ・ [Remote control from Feishu](#remote-control-from-feishu) ・ [FAQ](#faq) ・ [Security](#security) ・ [Why I built this](#why-i-built-this-plugin)
20
+ <p align="center">
21
+ <a href="#background--pain-points">Background & Pain Points</a> ·
22
+ <a href="#core-features">Core Features</a> ·
23
+ <a href="#ui-preview">UI Preview</a> ·
24
+ <a href="#desktop-remote-window">Remote Window</a> ·
25
+ <a href="#quick-start">Quick Start</a> ·
26
+ <a href="#usage--configuration">Usage & Configuration</a> ·
27
+ <a href="#license">License</a>
28
+ </p>
16
29
 
17
30
  ---
18
31
 
19
- ## What it is
20
-
21
- A plugin for [DeepSeek Harness](https://github.com/deepseek-ai/DeepSeek-Harness) (DSH, a plugin-extensible AI agent framework). Once installed:
22
-
23
- - a web page opens on your phone with exactly one input box and the latest reply;
24
- - instructions you send from the phone go straight to the session already running on your computer;
25
- - everything in between — tool calls, files read and written, sub-agents, the reasoning trace itself — **is never pushed to the phone**;
26
- - the only thing that "talks" is the whale girl: the line the model mutters between steps, spoken in her speech bubble.
32
+ ## Background & Pain Points
27
33
 
28
- Here is what the interface looks like — dark and light, switchable in settings (rendered at a phone size of 390×844):
34
+ When running complex engineering tasks with desktop or web AI agents, a single turn often involves several minutes of deep reasoning, dozens of file operations, and intensive tool executions. Existing mobile remote setups typically mirror the full desktop workspace onto the phone screen, causing practical friction:
29
35
 
30
- <img width="290" alt="Dark: one conversation, carrying only your instruction and the conclusion" src="https://raw.githubusercontent.com/xingzhen199186/dsh-mini-remote/main/docs/screen-dark.png" /> <img width="290" alt="Light: the same conversation, in the palette taken from the promo artwork" src="https://raw.githubusercontent.com/xingzhen199186/dsh-mini-remote/main/docs/screen-light.png" />
36
+ - **Imbalanced Information Density**: Raw reasoning traces, verbose tool parameters, and large unified diffs overwhelm small displays, burying the primary conclusion.
37
+ - **Attention Overload**: During commutes, meals, or brief breaks away from the keyboard, the primary goal is simply checking whether a round finished and dispatching the next instruction, without dissecting every intermediate step.
38
+ - **Inflexible Connectivity**: Pure LAN routes disconnect as soon as you step outside, while centralised cloud relays introduce external credential custody risks.
31
39
 
32
- It is **not** a second screen for the desktop interface. Approval dialogs, file diffs and tool-call chains exist on the computer and nowhere on the phone — deliberately. It does very little.
40
+ **Minimal Remote** was built to solve this: by default, the mobile view presents only your input and the AI's final answer, filtering out execution noise while allowing you to drill down into the full trace on demand.
33
41
 
34
- Other phone clients copy the computer's execution process over to the phone in full. This one does the opposite: **it sends only the two lines you asked for.** That is the single biggest difference between it and them.
42
+ ---
35
43
 
36
- ## When you'd use it
44
+ ## Core Features
37
45
 
38
- - **You're out and a task is still running.** The computer is at your desk mid-round; you just want to glance at the phone to see whether it finished, and hand it the next line while you're at it.
39
- - **You're with your kid, eating, or out for a walk.** You don't want to touch the computer, but an idea shows up and you'd like it working on that already.
40
- - **The computer is in the study and you're in the living room.** Not worth walking back, and not worth pulling that whole screen of process onto the phone.
46
+ - 🎛️ **Three On-Demand Presentation Modes**: Switch instantly between "Single frame" (the cleanest view, keeping only the latest conclusion), "Chat" (standard conversation bubbles), and "Full" (inline tool calls and file diffs with keyword search).
47
+ - 📱 **Zero-Install Mobile Client**: the phone side is simply a web page — scan, open it in a browser, and that is the whole setup. No app to install, no account to create, no third-party server in between; you can add it to the home screen and it opens full-screen from there.
48
+ - 🌐 **Multi-Route Secure Connectivity**: Connect via LAN, Tailscale private network (supporting MagicDNS and HTTPS certificates), or Cloudflare Tunnel (for environments without public IPs). All routes coexist with dedicated QR codes and tokens.
49
+ - 🐬 **Lightweight Anthropomorphic Feedback**: Inter-step narrations are spoken aloud by the whale girl sprite in speech bubbles; execution progress and queued instructions are visualized on an exact scale, filtering out raw reasoning blocks.
50
+ - 💬 **Feishu Long-Connection Remote**: Direct bidirectional communication through the Feishu Open Platform WebSocket long connection without public ports, supporting text dialogue, multiple-choice responses, and the `/会话` switch command.
51
+ - 🗂️ **In-Place Mobile Session Management**: Rename, pin, archive, or fork sessions from the most recent completed turn directly on your phone, with clear indicators for pending approvals and questions.
52
+ - 💻 **Desktop Embedded "Remote Window"**: Adds a "Remote Window" shortcut to the left sidebar of the DSH desktop app: it lists the other computers you have paired, and clicking a row embeds that computer's DSH desktop interface in the main view; click the row again to exit and return to where you were. Cross-machine access is supported; see "Desktop \"Remote Window\"" below for the pairing steps.
53
+ - 🔒 **Rigorous Security Boundaries**: All API routes enforce constant-time token comparison to prevent timing side-channel attacks; built-in rate limiting locks out sources after 5 failed attempts in 1 minute; pairing data is accessible solely from the host loopback interface.
41
54
 
42
55
  ---
43
56
 
44
- ## Install
57
+ ## UI Preview
45
58
 
46
- ```powershell
47
- dsh plugin --profile web add dsh-mini-remote
48
- ```
59
+ ### Conversation Screen (Single Frame / Chat / Full)
49
60
 
50
- **You must restart DSH once after installing** (close the `dsh web` window and start it again), or "Phone Remote" will not appear in the left column. The startup log then prints the phone URL and password.
61
+ The mobile client is built with zero-dependency vanilla JavaScript and supports both high-contrast Dark and Light themes. One conversation has three readings: **Single Frame** keeps only the latest conclusion on screen, **Chat** lays the history out as back-and-forth bubbles, and **Full** puts every turn's execution trail back where it happened:
51
62
 
52
- The `web` in that command is a DSH **profile name** — the folder under `~/.dsh/profiles/`. Most people's default profile is called `web`; if yours isn't, use your own name instead.
63
+ <div align="center">
64
+ <img width="290" alt="Chat (dark): several turns of history laid out as back-and-forth bubbles" src="https://raw.githubusercontent.com/xingzhen199186/dsh-mini-remote/main/docs/screen-chat-dark.png" />
65
+ <img width="290" alt="Chat (light): the same conversation in the light theme" src="https://raw.githubusercontent.com/xingzhen199186/dsh-mini-remote/main/docs/screen-chat-light.png" />
66
+ </div>
53
67
 
54
- <details>
55
- <summary>Installing from GitHub source, from a local folder, and which DSH versions it fits</summary>
68
+ ### Settings Panel & Appearance
56
69
 
57
- Or straight from GitHub, if you would rather pin the source:
70
+ Switch presentation modes, color themes, or trigger manual reconnects from the settings overlay:
58
71
 
59
- ```powershell
60
- dsh plugin --profile web add github:xingzhen199186/dsh-mini-remote
61
- ```
72
+ <div align="center">
73
+ <img width="290" alt="Settings (dark): three display modes, appearance set to dark" src="https://raw.githubusercontent.com/xingzhen199186/dsh-mini-remote/main/docs/settings-dark.png" />
74
+ <img width="290" alt="Settings (light): the selected states and the primary button turn royal blue too" src="https://raw.githubusercontent.com/xingzhen199186/dsh-mini-remote/main/docs/settings-light.png" />
75
+ </div>
62
76
 
63
- If you already have the source on disk, you can point it at the folder:
77
+ ### Execution Animation
64
78
 
65
- ```powershell
66
- dsh plugin --profile web add <the folder you put the source in>
67
- ```
79
+ During task execution, the view presents an animated running state, elapsed timer, and queued task scale without unverified progress guesses:
68
80
 
69
- **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.
81
+ <div align="center">
82
+ <img width="290" alt="Running (dark): the whale girl running, 14s elapsed, one instruction on the queue scale" src="https://raw.githubusercontent.com/xingzhen199186/dsh-mini-remote/main/docs/running-dark-phone.jpg" />
83
+ <img width="290" alt="Running (light): the same run in the light theme, 14s elapsed, one instruction queued" src="https://raw.githubusercontent.com/xingzhen199186/dsh-mini-remote/main/docs/running-light-phone.jpg" />
84
+ </div>
70
85
 
71
- Settings follow the same rule: the settings are declared the standard DSH way, and on the 0.1.5-era library that ability does not exist yet — the plugin **still installs and works exactly as before**, it just loses the "applies immediately" behaviour mentioned below. On the **0.1.7 generation** that ability is fully there.
86
+ ### Remote Window (Desktop)
72
87
 
73
- </details>
88
+ No window switching and no remote desktop: click "Remote Window" in the DSH desktop left sidebar and the other computer's DSH interface is embedded right in the main panel. The bar on top holds "← Back to list / which computer this is / Try again"; while the interface displays normally it auto-hides, sliding out only when the mouse reaches the top edge.
74
89
 
75
- ---
90
+ <div align="center">
91
+ <img width="720" alt="Remote Window: another computer's DSH interface embedded in the main panel, with Remote Window selected in the left sidebar" src="https://raw.githubusercontent.com/xingzhen199186/dsh-mini-remote/main/docs/remote-window.png" />
92
+ </div>
76
93
 
77
- ## Connecting your phone: three routes, pick one
94
+ ---
78
95
 
79
- All three connection methods **exist at the same time**. Pick one, or leave several on.
96
+ ## Quick Start
80
97
 
81
- | Route | When to use it | What you install | What it costs |
82
- | --- | --- | --- | --- |
83
- | **LAN** | Phone and computer on the same Wi-Fi — at home only | Nothing at all | It stops the moment you leave the house |
84
- | **Tailscale** | You need it outside, and you want the address to stay fixed | Tailscale on the computer and on the phone | An app on both sides |
85
- | **Public tunnel** | Nothing installed, reachable on any network | Nothing at all | The address changes on every restart; the first run downloads a ~50 MB component |
98
+ ### Prerequisites
86
99
 
87
- There is one more route, and it isn't the phone: **Feishu** (see [Remote control from Feishu](#remote-control-from-feishu)). It never touches the browser, and none of the three routes above need to be on.
100
+ Before installing, make sure this computer meets the following requirements:
88
101
 
89
- 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.
102
+ - **Node.js**: `^22.19.0 || >=24.0.0`
103
+ - **DSH (DeepSeek Harness)**: `>=0.1.5-rc.2 <0.3.0`
104
+ - **OS**: Windows, macOS, or Linux
90
105
 
91
- The plugin's own settings (default mode, external notifications, port, password and so on) also have a standard declaration, so writing them in DSH's standard configuration works too. If the same item is set in both places, **the standard configuration wins**. One difference worth knowing: **"default mode" and "external notifications" apply immediately, with no plugin restart**; port, bind address, tunnel, password and history length make the plugin restart and the phone reconnect once — those genuinely need to re-bind or rebuild, and the plugin says so instead of pretending they can be changed live.
106
+ > ⚠️ **Notice**: DSH is in active development. This plugin is verified across `0.1.5-rc.2`, `0.1.7-rc.2`, `0.2.0-rc.1`, and `0.2.0-rc.2`. Versions below `0.1.5` are untested, and versions above `0.3.0` risk breaking changes in upstream host interfaces — **`0.3.0` is the upper bound this release declares**. Once DSH moves past it, wait for the plugin to catch up instead of upgrading straight away.
92
107
 
93
- ### 1. LAN: at home only
108
+ ### Installation
94
109
 
95
- 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. The cost is that it stops working the moment you leave: the phone switches to mobile data and this route is gone.
110
+ #### Option 1: Install via DSH Desktop UI (Recommended)
96
111
 
97
- ### 2. Tailscale: works outside, and the address stays fixed
112
+ 1. Click the "Plugins" button on the top navigation bar of DSH to open the plugin manager.
113
+ 2. Click the "Add Plugin" button in the upper-right corner to open the installation dialog.
114
+ 3. Enter the package name `dsh-mini-remote` into the input field (GitHub repository URL `github:xingzhen199186/dsh-mini-remote` or local directory path is also supported). Keep the default registry ("npm official registry").
115
+ 4. Click the "Install" button at the bottom of the dialog.
98
116
 
99
- 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. The cost is an app on each side; if you don't mind installing it, **this is the steadiest route when you're out**.
117
+ > ⚠️ **Notice**:
118
+ > 1. **Verify trusted source**: Plugins run on your machine with your current user privileges. Plugins from untrusted sources may damage DeepSeek Harness or read and leak sensitive data.
119
+ > 2. **No automatic updates yet**: Installed plugins currently do not support automatic updates. To upgrade to a newer version, uninstall the existing version before installing the new one.
100
120
 
101
- There's a switch on the pairing page that gets you 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.
121
+ #### Option 2: Install from npm (Command Line)
102
122
 
103
- 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.
123
+ Execute the installation command in your terminal. Replace `web` with your custom profile name if you are not using the default profile:
104
124
 
105
- ### 3. Public tunnel: nothing to install
125
+ ```powershell
126
+ dsh plugin --profile web add dsh-mini-remote
127
+ ```
106
128
 
107
- 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**.
129
+ #### Option 3: Install from GitHub
108
130
 
109
- Two costs, worth knowing before you decide:
131
+ ```powershell
132
+ dsh plugin --profile web add github:xingzhen199186/dsh-mini-remote
133
+ ```
110
134
 
111
- - **The address changes every time you restart DSH.** When it does, come back and scan the new code.
112
- - **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.
135
+ #### Option 4: Install from Local Directory
113
136
 
114
- 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.
137
+ ```powershell
138
+ dsh plugin --profile web add C:\path\to\dsh-mini-remote
139
+ ```
115
140
 
116
- ### About that "encrypted address"
141
+ ### Starting the Service
117
142
 
118
- Two of the routes above can hand you an `https://` address, and what encryption covers is **the connection itself**: the address bar shows the https padlock, and what travels the wire is encrypted. That does not depend on which route you pick — both give the same thing.
143
+ 1. Restart the DSH service (close the active `dsh web` window and launch it again).
144
+ 2. Check the console log for the listening port and pairing token:
145
+ ```text
146
+ [dsh-mini-remote] 已启动:http://127.0.0.1:3090/mini?token=xxxxxxxxxxxx
147
+ ```
148
+ 3. Open the DSH desktop UI, navigate to "Settings" → "Phone Remote" in the left sidebar, and view the pairing QR codes and links.
119
149
 
120
- The difference is who can resolve the name. The Tailscale 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 you should use Tailscale IP addresses instead; 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.
150
+ > **The phone side is browser-only.** Scanning and opening it in a browser is the entire client — there is no standalone app and no mini-program. You can add the page to your home screen: the resulting icon opens full-screen and looks much like an app, but it is still the browser running the page. Switch phones or clear browser data, and you are back to scanning the code again.
151
+ >
152
+ > Conversely, this page **is not picky about the device either**: open the same address in a PC browser and it works just as well — and from there you can open the complete DSH desktop interface. See "Advanced Settings: Embedded Desktop Interface".
121
153
 
122
154
  ---
123
155
 
124
- ## What the phone can do
125
-
126
- Open the link and that's the whole interface: one input box, and the latest reply.
156
+ ## Usage & Configuration
127
157
 
128
- **Send instructions.** Type and send; the AI starts working on the computer.
158
+ ### Connection Route Matrix
129
159
 
130
- **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.
160
+ Select the route that matches your current networking environment:
131
161
 
132
- **She speaks up while she works.** On the computer, the model often mutters a line between steps ("let me look at this file first"). That line is now spoken by the whale girl through her speech bubble — the talking pose is a newly drawn sprite, the rotation pauses for it, and afterwards picks up from where it stopped. It stays **in the bubble** and never bleeds into the answer area below. Only the line it deliberately writes *for a human reader* is spoken; its own working thoughts — often English, often a whole paragraph — never reach the phone at all. Should that one narration line itself be in English, it is shown as-is, untranslated (translating would mean putting words in its mouth).
162
+ | Route | Scenario | Prerequisites | Trade-offs |
163
+ | :--- | :--- | :--- | :--- |
164
+ | **LAN** | Phone and computer on the same Wi-Fi subnet | None | Ready immediately; disconnects upon leaving Wi-Fi |
165
+ | **Tailscale** | Stable remote access across locations | Tailscale installed and logged in on both devices | Fixed private IP; optional HTTPS certificate support |
166
+ | **Public Tunnel** | No public IP and no third-party client installation | Enable Cloudflare Tunnel in settings | Temporary URL rotates on each DSH restart; initial setup downloads ~50 MB binary |
167
+ | **Feishu Long Connection** | Direct enterprise IM messaging without browser | Feishu custom bot credentials configured | No inbound ports required; bidirectional mobile approvals |
133
168
 
134
- **Two appearances, switchable anytime.** Settings has an "Appearance" row: **Dark** (the default), **Light**, and **Follow system**. Dark is deep-sea navy; the light palette is taken from the promo artwork — near-white ice blue for the ground, deep royal blue for the text, and the same royal blue on primary buttons. Your choice is stored on the phone, so it is still there next time you open the page.
169
+ ### Mobile Interface Guide
135
170
 
136
- <img width="290" alt="Settings (dark): display mode and appearance" src="https://raw.githubusercontent.com/xingzhen199186/dsh-mini-remote/main/docs/settings-dark.png" /> <img width="290" alt="Settings (light): the selected states and the primary button turn royal blue too" src="https://raw.githubusercontent.com/xingzhen199186/dsh-mini-remote/main/docs/settings-light.png" />
171
+ - **Sending & Queuing**: Enter instructions in the bottom input box. When an agent is busy, subsequent messages queue up sequentially and appear on the scale.
172
+ - **Slash Commands**: Type `/` to bring up available session commands with parameter guidance and search filtering.
173
+ - **Interactive Questions**: When the agent requests clarification or user choice, an interactive card pops up for one-tap answers or custom replies.
174
+ - **Back to Bottom**: When scrolling through long message histories, a floating "Back to bottom" button appears in the lower-right corner (disabled in Single frame mode).
175
+ - **Permission Switching**: Tap the top status bar to cycle between View Only (`read-only`), Workspace Write (`workspace-write`), and Full Access (`danger-full-access`).
137
176
 
138
- **The screen while a task is running.** She is mid-stride, the progress bar is moving, and the queue lists what goes next once this round ends. No tool calls and no file diffs on this screen — only the fact that something is running.
177
+ > ⚠️ **Notice**:
178
+ > 1. Elevating permissions to "Full Access" permits the agent to run arbitrary system commands and modify files across the machine. Proceed with caution.
179
+ > 2. System-level confirmation dialogs for dangerous commands belong to the DSH on your computer itself — the phone cannot approve them, so you will need to handle those on the computer.
139
180
 
140
- <img width="290" alt="Running (dark, photographed on a phone): the whale girl running, 15s elapsed" src="https://raw.githubusercontent.com/xingzhen199186/dsh-mini-remote/main/docs/running-dark-phone.jpg" /> <img width="290" alt="Running (light, photographed on a phone): the whale girl running, 7m43s elapsed, one instruction queued" src="https://raw.githubusercontent.com/xingzhen199186/dsh-mini-remote/main/docs/running-light-phone.jpg" />
181
+ ### Advanced Settings: Embedded Desktop Interface (Phone or PC Browser)
141
182
 
142
- Both are phone photographs (the browser's own chrome is in frame, so they sit slightly taller than a render would).
183
+ **The remote page is not phone-only.** Open the same address (the one the QR code points at) in a PC browser and it works just the same — the layout is simply tuned for a phone screen. What makes this route genuinely useful on a PC is "Advanced settings": it embeds the complete DSH desktop interface, so you do not have to spin up a separate `dsh web`.
143
184
 
144
- **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.
185
+ How to open it:
145
186
 
146
- **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.
187
+ 1. Click the gear in the top-right corner, find the "Advanced settings" row (its hint reads "Open the DSH interface on the computer and change the settings the phone does not have"), and switch it to on.
188
+ 2. It asks once more — **you must confirm a second time**.
189
+ 3. A "Desktop interface" row appears right below (hint: "the complete desktop DSH page"). Click "Open".
190
+ 4. A full-screen copy of the DSH desktop interface is embedded right in this page: plugin management, model configuration, session history, and full logs. The bar on top exits back to the remote page.
147
191
 
148
- **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.
192
+ **It moves this computer's own interface over — it does not start a second one.** Whatever you change or send here happens **on this DSH**; the desktop app and this view share one state. Nor is it "spinning up another web instance": the plugin's server authenticates once through the official door, then **proxies every request** to the local interface in real time (even live UI refreshes are forwarded as they come, never buffered). The phone never touches any official credential.
149
193
 
150
- **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.
194
+ > ⚠️ **Notice**:
195
+ > 1. **This is a permission switch, not an ordinary preference.** Turning it on extends the token's reach from "what the phone page exposes" to the **entire desktop management plane** — model configuration, credentials, plugin install/uninstall, session history. It is therefore off by default and takes two confirmations to enable.
196
+ > 2. What gets embedded is the desktop interface as-is — on a narrow phone screen it adapts to its mobile layout; in a PC browser you get the original.
151
197
 
152
- **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.
198
+ ### Desktop "Remote Window"
153
199
 
154
- **You're reading conclusions, not the process.** There's no tool-call chain and no file diff on the page. The one exception is the line the whale girl says out loud — it goes into her bubble, never into the answer area (see above). **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.
200
+ **In one sentence**: open computer A's DSH interface directly inside computer B's DSH desktop window.
155
201
 
156
- ---
157
-
158
- ## Remote control from Feishu
202
+ **What it replaces**: when both machines run their own DSH, looking at the other one used to take one of two detours — an extra browser window (so you keep switching between two sets of windows), or full remote desktop (the entire screen comes over, with all the resolution and shortcut friction). This entry turns "that machine" into one panel: click and it is there, click again and you are back where you were.
159
203
 
160
- **Talk to the session on your computer from inside Feishu.** You send a line, the session runs a round, and the answer comes back under your message — with one more line underneath saying which session it came from (`会话:deploy script`, and `未命名会话` when the session has no name yet). Those two labels are Chinese and stay as they are.
204
+ #### What it looks like in use
161
205
 
162
- It runs over Feishu's **long connection**: the plugin dials out to Feishu and keeps the line open, so there is no public address and no domain to arrange. It shares one session binding with the phone page.
206
+ 1. Click "Remote Window" in the left sidebar; the main view lists the computers you have paired — one row each, with name, address, and when it last connected.
207
+ 2. Click a row and that computer's interface is embedded in the panel.
208
+ 3. Click the sidebar row again (icon, label, or any blank part of the row) to leave and return to the panel you were on.
163
209
 
164
- ### Setup
210
+ While the interface displays normally, the bar at the top **auto-hides** — move the mouse to the top edge and it slides out. The bar carries "← Back to list", which computer this is, and "Try again": that is the only way out (and the way to retry) when something goes wrong, so in the connecting, failed, and never-loaded states **it stays visible and never hides**.
165
211
 
166
- Create an app in the [Feishu open platform](https://open.feishu.cn/) — the "custom app" type, which is also what you would use for yourself alone. Copy the App ID and App Secret from Credentials & Basic Info. **Then add a Bot capability and publish a version** — skip that step and the bot will not show up in Feishu search. Set the event subscription mode to "receive events over a long connection", and add the event `im.message.receive_v1`. Under permissions, search for just `im.message` (typing the rest of the name returns nothing) and tick three: receive messages, send messages as the app, get and send single-chat and group messages — **the count going from 0 to 3 is your proof you got it**. Any change to the capability, the permissions or the events needs another published version. Then back in DSH settings, fill the App ID and App Secret into "Phone Remote" → "Feishu" and turn the switch on.
212
+ #### What was done for security
167
213
 
168
- Every menu and the sign of a successful publish are in the "配置指引(飞书后台六步)" guide inside that settings block. It is **collapsed by default**. The paragraph above only tells you how many things there are to do; it does not repeat the guide.
214
+ - **The pass never changes hands**: opening a window makes the server sign a one-time ticket (valid for 30 seconds, redeemable once). The browser receives that ticket only — **your access pass and long-lived credentials never enter the browser**, so they cannot end up in browsing history or inside the embedded page.
215
+ - **Only a page carrying a valid ticket may embed**: cross-site embedding is denied by default and allowed only for that one ticket-bearing load. An outside page that learns the address still cannot get in.
216
+ - **Revocation is immediate**: once you revoke device B on A, B's already-open window fails on its next request — no waiting for it to disconnect on its own.
217
+ - **It dies with DSH**: restarting DSH invalidates that screen's pass; click once more to reopen.
169
218
 
170
- ### The first message is refused, and that's expected
219
+ #### Cross-Machine Setup (Two Computers)
171
220
 
172
- Both allow-lists start empty, and **with both empty nobody is recognised**. So your first message to the bot does nothing. The plugin **answers you inside Feishu** instead: it hands you your own id (`open_id`, the internal number Feishu knows you by) and tells you which field it goes in. Paste it into "允许的 open_id", save, and send again — that one works.
221
+ Below, **A** is the computer being connected to, and **B** is the one connecting to it.
173
222
 
174
- Only **direct messages** are handled (you and the bot, one to one). Group messages are not read in this version.
223
+ **On A**
175
224
 
176
- ### What you can do from Feishu
225
+ 1. **Install this plugin, version `0.2.1` or newer.** "Remote Window" first shipped in `0.2.1` — B connects to the code running on A, so if A is on an older version, B sees the old interface.
226
+ 2. Open "Settings → Phone Remote → Allow other computers to connect" and switch it on. It is off by default; while it is off, A does not accept pairing requests at all.
227
+ 3. In the "Password" section of the same settings page, click "Copy" to get A's pass.
177
228
 
178
- **Plain text is you talking to the current session** — the same as sending it from the phone.
229
+ **On B** (in B's "Settings → Phone Remote")
179
230
 
180
- **When the session stops to ask you something, an ordinary text message arrives in Feishu.** A multiple-choice question lists its options as `1.` `2.`; an approval spells out which tool and which command it wants to run. Reply with a number, or with 「同意」 (agree) or 「拒绝」 (refuse) — `y`, `yes` and `ok` count as agree, `n` and `no` as refuse. Reply 「取消」 to decline to decide: the question goes back to the computer. That word has to be 「取消」; the English "cancel" is not read.
231
+ The section you need is "Other computers", near the bottom of the settings page. It is the mirror image of the "Devices" section above — that one lists who can get in, this one lists whom you can reach.
181
232
 
182
- **`/会话` lists the sessions you can switch to**, marking the current one 「(当前)」. **`/会话 3`** switches to the third, and the phone page follows — the two sides share one binding. Anything starting with `/` is treated as a command and never as an answer to a pending question. It is the only command here, and it is Chinese; send those characters as they are.
233
+ 1. Click "Add a computer" to unfold three fields.
234
+ 2. **That computer's address (the one on its "Phone Remote" page, no `/mini`)** — enter A's address. This is the field that matters most; see "Which address to enter" below.
235
+ 3. **That computer's pass (copy it from its "Phone Remote" settings)** — paste what you copied in step 3 on A. This field is masked.
236
+ 4. **Give it a name (optional; the address is used if you leave it blank)** — so you can tell it apart in the list.
237
+ 5. Click "Confirm add". This really does pair with A once — afterwards A's settings page gains a "this computer" entry and B gains a row.
238
+ 6. Click that row in the list.
183
239
 
184
- **Not there yet.** Cards with buttons; images and files; group chats; streaming — the answer arrives in one piece, after a wait; one round at a time.
240
+ Each row shows the name, the address, `last ok <time>` (or "no record yet"), and two buttons on the right: **"Reconnect"** fetches a fresh pass, **"Disconnect"** removes the pairing. Disconnecting asks once and states that the entry on the far computer **stays** — to revoke it fully, remove this device on A.
185
241
 
186
- ---
242
+ **Which address to enter**
187
243
 
188
- ## FAQ
244
+ - Enter the address shown on A's "Phone Remote" page (no trailing `/mini` needed) — **not** the one you use to open the DSH interface on A itself.
245
+ - **It must be `https://`.** A plain `http://` address can pair and can obtain the pass, but the frame stays blank — the browser drops that pass on a non-HTTPS address.
246
+ - Tailscale is recommended: switch on "HTTPS address (Tailscale)" on A, then enter `https://<machine>.<your-tailnet>.ts.net` on B — **no port needed**. The address is stable, so you set it once.
247
+ - The "Public access" tunnel address changes on every restart, so it is not suitable for cross-machine use.
189
248
 
190
- **The QR code scans but the page won't open.**
191
- First check that the phone and the computer are on the same Wi-Fi.
249
+ **How to tell it worked**
192
250
 
193
- **Scanning the "public" route from outside won't open.**
194
- 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**.
251
+ Click the row in the list and that computer's interface appears in the frame. When something fails, an explanation appears under that row — the far side has not switched it on, the pairing was revoked, it is unreachable, or the address is wrong; each has its own message.
195
252
 
196
- **It says "disconnected".**
197
- 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".
253
+ **Revoking a computer later**
198
254
 
199
- **The reply arrives but there's no sound.**
200
- Audio only plays after you've touched the page once. Tap it.
255
+ On A, open "Settings → Phone Remote → Devices" — the list of who can get in, each row carrying "Rename" and "Revoke". Find that computer, click "Revoke", then "Confirm revoke". **It takes effect immediately**: a window the far side already has open fails on its next request; no need to wait for it to disconnect.
201
256
 
202
- **The phone keeps asking for a password.**
203
- 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.
257
+ ### Feishu Bot Setup Guide
204
258
 
205
- **I want a password I can remember.**
206
- 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.
207
-
208
- ---
259
+ 1. Log in to the [Feishu Open Platform](https://open.feishu.cn/) and create a custom enterprise application.
260
+ 2. Record the `App ID` and `App Secret` under Credentials & Basic Info.
261
+ 3. Navigate to "Add Capabilities" and add the "Bot" capability.
262
+ 4. Navigate to "Events & Callbacks", set the subscription mode to "Receive events over a long connection", and subscribe to `im.message.receive_v1`.
263
+ 5. Under "Permissions", grant the following 3 scopes:
264
+ - Receive messages (`im:message:receive_v1`)
265
+ - Send messages as bot (`im:message:send_as_bot`)
266
+ - Read and send single/group chat messages (`im:message.group_at_msg:readonly` suite)
267
+ 6. Create and **publish an application version**.
268
+ 7. Return to DSH desktop "Settings" → "Phone Remote" → "Feishu", paste the credentials, and turn the toggle on. The first time you message the bot, it replies with your `open_id`. Add this ID to the allow-list to finish onboarding.
209
269
 
210
- ## Security
270
+ ### Configuration Parameters
211
271
 
212
- **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.
272
+ Settings can be managed either via the desktop "Phone Remote" panel or declared directly in the standard DSH profile:
213
273
 
214
- 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. **The one exception is images**: when something the AI wants to show you includes a picture (an interface screenshot, say), that image is placed under the plugin's `lib/art/` directory with a name starting with `out-`, and the page fetches it over the same password-protected image route the sprites use. Only that one class of file — an image, with that prefix — can be fetched; message bodies, configuration files and everything else stay unreadable, and directories still cannot be listed. **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.
274
+ | Parameter | Type | Default | Lifecycle | Description |
275
+ | :--- | :--- | :--- | :--- | :--- |
276
+ | `port` | `number` | `3090` | Restart required | Local HTTP port for the remote service (auto-increments on conflict) |
277
+ | `token` | `string` | *(generated)* | Restart required | Access token (must be at least 12 characters if customized) |
278
+ | `defaultMode` | `string` | `"minimal"` | Immediate | Default view mode on mobile: `"minimal"`, `"chat"`, `"full"` |
279
+ | `externalNotify` | `boolean` | `true` | Immediate | Play chimes and vibrate on task completion |
280
+ | `tunnel.enabled` | `boolean` | `false` | Restart required | Enable Cloudflare temporary public tunnel |
281
+ | `tailscale.serve` | `boolean` | `false` | Restart required | Enable Tailscale HTTPS certificate listener |
282
+ | `feishu.enabled` | `boolean` | `false` | Immediate | Enable Feishu WebSocket long connection |
215
283
 
216
284
  ---
217
285
 
218
- ## Why I built this plugin
219
-
220
- 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.
221
-
222
- 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.
223
-
224
- 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.
225
-
226
- 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.
227
-
228
- 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.
229
-
230
- **In a sense, it exists so that you look at it less.**
286
+ ## License
231
287
 
232
- 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.
288
+ This project is licensed under the [MIT License](LICENSE).
233
289
 
234
- ---
290
+ ### Documentation & Reference Links
235
291
 
236
- ## Credits
292
+ - [Sprites and Animation Guide](docs/character.md) (Chinese): Image tool pipelines, shared prompt templates, dimensions, and acceptance criteria.
293
+ - [Sprite Reference Frames (Frozen 2026-09-28)](docs/art-refs/2026-09-28/) (Chinese): Reference frames and prompt baselines.
294
+ - [Changelog](CHANGELOG.md): Historical evolution and bug fix records.
295
+ - [Repository](https://github.com/xingzhen199186/dsh-mini-remote): Official GitHub home.
237
296
 
238
- 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.
239
-
240
- ## License
297
+ ### Credits
241
298
 
242
- MIT
299
+ Special thanks to [dsh-pocket](https://www.npmjs.com/package/dsh-pocket) by @shaobeichen for inspiring the multi-path independent QR pairing layout.