dsh-mini-remote 0.2.0 → 0.2.2

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/README.en.md CHANGED
@@ -1,248 +1,314 @@
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="#mobile-interface-guide">Mobile Usage</a> ·
25
+ <a href="#desktop-remote-window">Remote Window</a> ·
26
+ <a href="#quick-start">Quick Start</a> ·
27
+ <a href="#usage--configuration">Usage & Configuration</a> ·
28
+ <a href="#license">License</a>
29
+ </p>
16
30
 
17
31
  ---
18
32
 
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.
33
+ ## Background & Pain Points
27
34
 
28
- Here is what the interface looks like — dark and light, switchable in settings (rendered at a phone size of 390×844):
35
+ 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
36
 
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" />
37
+ - **Imbalanced Information Density**: Raw reasoning traces, verbose tool parameters, and large unified diffs overwhelm small displays, burying the primary conclusion.
38
+ - **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.
39
+ - **Inflexible Connectivity**: Pure LAN routes disconnect as soon as you step outside, while centralised cloud relays introduce external credential custody risks.
31
40
 
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 default page — deliberately. It does very little. (If you want the **whole** desktop interface, there is an off-by-default entry in settings — see the last paragraph of [What the phone can do](#what-the-phone-can-do).)
41
+ **Minimal Remote** is built around exactly that: it fits several ways of working and hands attention control back to you. On mobile, three modes — "Single frame", "Chat" and "Full" — let you hide execution noise entirely, or expand the full trace whenever you want. On PC, the "Remote Window" feature lets you drive the DeepSeek Harness on your main machine from other devices, inside its own native desktop UI.
33
42
 
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.
43
+ ---
35
44
 
36
- ## When you'd use it
45
+ ## Core Features
37
46
 
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.
47
+ - 🎛️ **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).
48
+ - 📱 **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.
49
+ - 🌐 **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.
50
+ - 🐬 **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.
51
+ - 💬 **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.
52
+ - 🗂️ **In-Place Mobile Session Management**: Open it as a web page in your phone's browser and rename, pin, archive, or fork sessions right there, with clear indicators for pending approvals and questions.
53
+ - 💻 **Desktop Embedded "Remote Window"**: A "Remote Window" shortcut in the DSH desktop left sidebar lets you operate another computer's DSH desktop remotely, with native-feeling window transitions and no page switch; see "Desktop \"Remote Window\"" below for the pairing steps.
54
+ - 🔒 **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
55
 
42
56
  ---
43
57
 
44
- ## Install
58
+ ## UI Preview
45
59
 
46
- ```powershell
47
- dsh plugin --profile web add dsh-mini-remote
48
- ```
60
+ ### Conversation Screen (Single Frame / Chat / Full)
49
61
 
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.
62
+ 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
63
 
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.
64
+ <div align="center">
65
+ <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" />
66
+ <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" />
67
+ </div>
53
68
 
54
- <details>
55
- <summary>Installing from GitHub source, from a local folder, and which DSH versions it fits</summary>
69
+ ### Settings Panel & Appearance
56
70
 
57
- Or straight from GitHub, if you would rather pin the source:
71
+ Switch presentation modes, color themes, or trigger manual reconnects from the settings overlay:
58
72
 
59
- ```powershell
60
- dsh plugin --profile web add github:xingzhen199186/dsh-mini-remote
61
- ```
73
+ <div align="center">
74
+ <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" />
75
+ <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" />
76
+ </div>
62
77
 
63
- If you already have the source on disk, you can point it at the folder:
78
+ ### Execution Animation
64
79
 
65
- ```powershell
66
- dsh plugin --profile web add <the folder you put the source in>
67
- ```
80
+ During task execution, the view presents an animated running state, elapsed timer, and queued task scale without unverified progress guesses:
68
81
 
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**; **0.2.0 itself was built on 0.2.0-rc.1 / 0.2.0-rc.2** (every interface it uses was unchanged, and the full check suite ran on both sides). **Versions below 0.1.5 have not been tried**, and the declared ceiling is **0.3.0**. `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.2.0 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. The phone-side interface adaptations also come with a dependency manifest and an **upgrade self-check** (`tools/structure-check.mjs`): run it against the live page after an upgrade and it walks every dependency entry by entry.
82
+ <div align="center">
83
+ <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" />
84
+ <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" />
85
+ </div>
70
86
 
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.
87
+ ### Remote Window (Desktop)
72
88
 
73
- </details>
89
+ 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
90
 
75
- ---
91
+ <div align="center">
92
+ <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" />
93
+ </div>
76
94
 
77
- ## Connecting your phone: three routes, pick one
95
+ ---
78
96
 
79
- All three connection methods **exist at the same time**. Pick one, or leave several on.
97
+ ## Quick Start
80
98
 
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 |
99
+ ### Prerequisites
86
100
 
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.
101
+ Before installing, make sure this computer meets the following requirements:
88
102
 
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.
103
+ - **Node.js**: `^22.19.0 || >=24.0.0`
104
+ - **DSH (DeepSeek Harness)**: `>=0.1.5-rc.2 <0.3.0`
105
+ - **OS**: Windows, macOS, or Linux
90
106
 
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.
107
+ > ⚠️ **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
108
 
93
- ### 1. LAN: at home only
109
+ ### Installation
94
110
 
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.
111
+ #### Option 1: Install via DSH Desktop UI (Recommended)
96
112
 
97
- ### 2. Tailscale: works outside, and the address stays fixed
113
+ 1. Click the "Plugins" button on the top navigation bar of DSH to open the plugin manager.
114
+ 2. Click the "Add Plugin" button in the upper-right corner to open the installation dialog.
115
+ 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").
116
+ 4. Click the "Install" button at the bottom of the dialog.
98
117
 
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**.
118
+ > ⚠️ **Notice**:
119
+ > 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.
120
+ > 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
121
 
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.
122
+ #### Option 2: Install from npm (Command Line)
102
123
 
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.
124
+ Execute the installation command in your terminal. Replace `web` with your custom profile name if you are not using the default profile:
104
125
 
105
- ### 3. Public tunnel: nothing to install
126
+ ```powershell
127
+ dsh plugin --profile web add dsh-mini-remote
128
+ ```
106
129
 
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**.
130
+ #### Option 3: Install from GitHub
108
131
 
109
- Two costs, worth knowing before you decide:
132
+ ```powershell
133
+ dsh plugin --profile web add github:xingzhen199186/dsh-mini-remote
134
+ ```
110
135
 
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.
136
+ #### Option 4: Install from Local Directory
113
137
 
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.
138
+ ```powershell
139
+ dsh plugin --profile web add C:\path\to\dsh-mini-remote
140
+ ```
115
141
 
116
- ### About that "encrypted address"
142
+ ### Starting the Service
117
143
 
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.
144
+ 1. Restart the DSH service (close the active `dsh web` window and launch it again).
145
+ 2. Check the console log for the listening port and pairing token:
146
+ ```text
147
+ [dsh-mini-remote] 已启动:http://127.0.0.1:3090/mini?token=xxxxxxxxxxxx
148
+ ```
149
+ 3. Open the DSH desktop UI, navigate to "Settings" → "Phone Remote" in the left sidebar, and view the pairing QR codes and links.
119
150
 
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.
151
+ > **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.
152
+ >
153
+ > 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
154
 
122
155
  ---
123
156
 
124
- ## What the phone can do
125
-
126
- Open the link and that's the whole interface: one input box, and the latest reply.
127
-
128
- **Send instructions.** Type and send; the AI starts working on the computer.
129
-
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.
131
-
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).
133
-
134
- **Two appearances, switchable anytime.** Settings has an "Appearance" row: **Dark**, **Light** (the default), 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.
135
-
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" />
157
+ ## Usage & Configuration
137
158
 
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.
159
+ ### Connection Route Matrix
139
160
 
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" />
161
+ Select the route that matches your current networking environment:
141
162
 
142
- **Three 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. "Full" takes that same list and **puts each step's process back in its original place** (the same shape the desktop app uses), with layers you can open one by one to see what that step read — and it is searchable. Use it for a while and you'll know which you prefer.
163
+ | Route | Scenario | Prerequisites | Trade-offs |
164
+ | :--- | :--- | :--- | :--- |
165
+ | **LAN** | Phone and computer on the same Wi-Fi subnet | None | Ready immediately; disconnects upon leaving Wi-Fi |
166
+ | **Tailscale** | Stable remote access across locations | Tailscale installed and logged in on both devices | Fixed private IP; optional HTTPS certificate support |
167
+ | **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 |
168
+ | **Feishu Long Connection** | Direct enterprise IM messaging without browser | Feishu custom bot credentials configured | No inbound ports required; bidirectional mobile approvals |
143
169
 
144
- **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.
170
+ ### Mobile Interface Guide
145
171
 
146
- **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.
172
+ **First, get the address of this page.** Open "Settings → Phone Remote" in the DSH desktop app; it lists **every address this computer can be reached at** — "This machine", "LAN", "Tailscale", "Tailscale (encrypted)", "Public access". Which ones appear depends on what this computer has installed and switched on.
147
173
 
148
- **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.
174
+ Each one is a block: **QR code on the left, the full URL on the right**. Scanning the QR code with the phone is the easiest way; to type it on another device, click "Copy" on the right, or click into the URL field (it selects the whole address for you).
149
175
 
150
- **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.
176
+ An address looks like this:
151
177
 
152
- **By default you're reading conclusions, not the process.** In Single frame and Chat there is no tool-call chain and no file diff; the one exception is the line the whale girl says out loud — it goes into her bubble, never into the answer area (see above). To read the process you switch to "Full" yourself. **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.
178
+ ```text
179
+ http://192.168.1.2:3090/mini?token=xxxxxxxxxxxx
180
+ ```
153
181
 
154
- **The whole desktop interface can be brought over too ("Advanced settings").** Settings has an **off-by-default** "Advanced settings" entry: turn it on and a "Desktop interface" row appears below it; tap "Open" and the computer's full DSH page is embedded right there on the phone — no jump, no new tab — so model configuration, plugin install and removal, session records and anything else the remote page doesn't have can be done from here. **It is the exact opposite of the positioning above** (switch it on and the whole process is on screen), which is why it starts off: turning it on spells the consequence out (the password's reach extends to the entire desktop settings surface) and takes two taps to confirm. When the plugin cannot learn the desktop address, the entry does not appear at all.
182
+ > ⚠️ **That URL carries the access pass** — whoever gets it can operate this computer. Do not screenshot it to others, and do not paste it anywhere public. To change the pass, see the "Password" section in the settings page.
155
183
 
156
- ---
184
+ Once you are in, this page lets you:
157
185
 
158
- ## Remote control from Feishu
186
+ - **Sending & Queuing**: Enter instructions in the bottom input box. When an agent is busy, subsequent messages queue up sequentially and appear on the scale.
187
+ - **Slash Commands**: Type `/` to bring up available session commands with parameter guidance and search filtering.
188
+ - **Interactive Questions**: When the agent requests clarification or user choice, an interactive card pops up for one-tap answers or custom replies.
189
+ - **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).
190
+ - **Permission Switching**: Tap the top status bar to cycle between View Only (`read-only`), Workspace Write (`workspace-write`), and Full Access (`danger-full-access`).
159
191
 
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.
192
+ > ⚠️ **Notice**:
193
+ > 1. Elevating permissions to "Full Access" permits the agent to run arbitrary system commands and modify files across the machine. Proceed with caution.
194
+ > 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.
161
195
 
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.
196
+ ### Advanced Settings: Embedded Desktop Interface (Phone or PC Browser)
163
197
 
164
- ### Setup
198
+ **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`.
165
199
 
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.
200
+ How to open it:
167
201
 
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.
202
+ 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.
203
+ 2. It asks once more — **you must confirm a second time**.
204
+ 3. A "Desktop interface" row appears right below (hint: "the complete desktop DSH page"). Click "Open".
205
+ 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.
169
206
 
170
- ### The first message is refused, and that's expected
207
+ **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.
171
208
 
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.
209
+ > ⚠️ **Notice**:
210
+ > 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.
211
+ > 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.
173
212
 
174
- Only **direct messages** are handled (you and the bot, one to one). Group messages are not read in this version.
213
+ ### Desktop "Remote Window"
175
214
 
176
- ### What you can do from Feishu
215
+ **In one sentence**: open computer A's DSH interface directly inside computer B's DSH desktop window.
177
216
 
178
- **Plain text is you talking to the current session** — the same as sending it from the phone.
217
+ **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.
179
218
 
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.
219
+ #### What it looks like in use
181
220
 
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.
221
+ 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.
222
+ 2. Click a row and that computer's interface is embedded in the panel.
223
+ 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.
183
224
 
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.
225
+ 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**.
185
226
 
186
- ---
227
+ #### What was done for security
187
228
 
188
- ## FAQ
229
+ - **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.
230
+ - **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.
231
+ - **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.
232
+ - **It dies with DSH**: restarting DSH invalidates that screen's pass; click once more to reopen.
189
233
 
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.
234
+ #### Cross-Machine Setup (Two Computers)
192
235
 
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**.
236
+ Below, **A** is the computer being connected to, and **B** is the one connecting to it.
195
237
 
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".
238
+ **On A**
198
239
 
199
- **The reply arrives but there's no sound.**
200
- Audio only plays after you've touched the page once. Tap it.
240
+ 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.
241
+ 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.
242
+ 3. In the "Password" section of the same settings page, click "Copy" to get A's pass.
201
243
 
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.
244
+ **On B** (in B's "Settings → Phone Remote")
204
245
 
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.
246
+ 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.
207
247
 
208
- ---
248
+ 1. Click "Add a computer" to unfold three fields.
249
+ 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.
250
+ 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.
251
+ 4. **Give it a name (optional; the address is used if you leave it blank)** — so you can tell it apart in the list.
252
+ 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.
253
+ 6. Click that row in the list.
209
254
 
210
- ## Security
255
+ 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.
211
256
 
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.
257
+ **Which address to enter**
213
258
 
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.
259
+ - 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.
260
+ - **It must be `https://`.** A plain `http://` address can pair and can fetch a ticket, but the frame stays blank: on the way in, the browser has to store a cookie for this screen (every request inside the frame is then identified by it), and it will only store such a cookie over an encrypted connection. On an http address that cookie is dropped outright, so every later request is refused. Local `127.0.0.1` is the one exception — browsers treat loopback as a trusted origin — which is why this restriction only bites cross-machine setups.
261
+ - 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.
262
+ - The "Public access" tunnel address changes on every restart, so it is not suitable for cross-machine use.
215
263
 
216
- ---
264
+ **How to tell it worked**
217
265
 
218
- ## Why I built this plugin
266
+ 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.
219
267
 
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.
268
+ **Revoking a computer later**
221
269
 
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.
270
+ 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.
223
271
 
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.
272
+ ### Feishu Bot Setup Guide
225
273
 
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.
274
+ 1. Log in to the [Feishu Open Platform](https://open.feishu.cn/) and create a custom enterprise application.
275
+ 2. Record the `App ID` and `App Secret` under Credentials & Basic Info.
276
+ 3. Navigate to "Add Capabilities" and add the "Bot" capability.
277
+ 4. Navigate to "Events & Callbacks", set the subscription mode to "Receive events over a long connection", and subscribe to `im.message.receive_v1`.
278
+ 5. Under "Permissions", grant the following 3 scopes:
279
+ - Receive messages (`im:message:receive_v1`)
280
+ - Send messages as bot (`im:message:send_as_bot`)
281
+ - Read and send single/group chat messages (`im:message.group_at_msg:readonly` suite)
282
+ 6. Create and **publish an application version**.
283
+ 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.
227
284
 
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.
285
+ ### Configuration Parameters
229
286
 
230
- **In a sense, it exists so that you look at it less.**
287
+ Settings can be managed either via the desktop "Phone Remote" panel or declared directly in the standard DSH profile:
231
288
 
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.
289
+ | Parameter | Type | Default | Lifecycle | Description |
290
+ | :--- | :--- | :--- | :--- | :--- |
291
+ | `port` | `number` | `3090` | Restart required | Local HTTP port for the remote service (auto-increments on conflict) |
292
+ | `token` | `string` | *(generated)* | Restart required | Access token (must be at least 12 characters if customized) |
293
+ | `defaultMode` | `string` | `"minimal"` | Immediate | Default view mode on mobile: `"minimal"`, `"chat"`, `"full"` |
294
+ | `externalNotify` | `boolean` | `true` | Immediate | Play chimes and vibrate on task completion |
295
+ | `tunnel.enabled` | `boolean` | `false` | Restart required | Enable Cloudflare temporary public tunnel |
296
+ | `tailscale.serve` | `boolean` | `false` | Restart required | Enable Tailscale HTTPS certificate listener |
297
+ | `feishu.enabled` | `boolean` | `false` | Immediate | Enable Feishu WebSocket long connection |
233
298
 
234
299
  ---
235
300
 
236
- ## For maintainers
237
-
238
- After upgrading DSH, run `node tools/structure-check.mjs` once. It reports entry by entry: which ones still hold, which have drifted, and whether a drifted one actually needs attention. When anything has drifted the exit code is 1, so the check can be wired into a pipeline later.
301
+ ## License
239
302
 
240
- ---
303
+ This project is licensed under the [MIT License](LICENSE).
241
304
 
242
- ## Credits
305
+ ### Documentation & Reference Links
243
306
 
244
- 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.
307
+ - [Sprites and Animation Guide](docs/character.md) (Chinese): Image tool pipelines, shared prompt templates, dimensions, and acceptance criteria.
308
+ - [Sprite Reference Frames (Frozen 2026-09-28)](docs/art-refs/2026-09-28/) (Chinese): Reference frames and prompt baselines.
309
+ - [Changelog](CHANGELOG.md): Historical evolution and bug fix records.
310
+ - [Repository](https://github.com/xingzhen199186/dsh-mini-remote): Official GitHub home.
245
311
 
246
- ## License
312
+ ### Credits
247
313
 
248
- MIT
314
+ Special thanks to [dsh-pocket](https://www.npmjs.com/package/dsh-pocket) by @shaobeichen for inspiring the multi-path independent QR pairing layout.