dsh-remote 0.7.1 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +189 -174
- package/README.zh.md +178 -165
- package/cordis.patch.yml +24 -6
- package/lib/client.js +788 -770
- package/lib/index.js +1810 -1736
- package/package.json +62 -61
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 dsh-remote contributors
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-remote contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,175 +1,190 @@
|
|
|
1
|
-
**English** · [中文](./README.zh.md)
|
|
2
|
-
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# dsh-remote
|
|
6
|
-
|
|
7
|
-
[](https://www.npmjs.com/package/dsh-remote)
|
|
8
|
-
[](LICENSE)
|
|
9
|
-
[](https://github.com/topics/dsh-plugin)
|
|
10
|
-
|
|
11
|
-
**Remote-work assistant for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH).**
|
|
12
|
-
|
|
13
|
-
Manage several SSH machines, then pick a **remote workspace** (or a **local** one) and let the agent operate right there without leaving the harness — listing files, reading code, running builds & commands over the remote host, and keeping that remote directory mirrored into a real local workspace object.
|
|
14
|
-
|
|
15
|
-
The harness Web UI intentionally binds `127.0.0.1` (the CLI rejects `--host 0.0.0.0` for safety). This plugin goes the other way: **you connect out** to the machines you maintain, pick a workspace, and work in it through the normal DSH workspace + agent fs flows — no changes to `dsh-workspace` or the harness core.
|
|
16
|
-
|
|
17
|
-
## Screen previews
|
|
18
|
-
|
|
19
|
-
Settings → **远程工作区** — a multi-machine SSH registry (add / edit / delete / set-current, password stored locally):
|
|
20
|
-
|
|
21
|
-
<img src="https://cdn.jsdelivr.net/gh/flymysql/dsh-remote@main/docs/ui-settings-panel.png" alt="dsh-remote settings — multi-machine registry (light theme, host scrubbed)" width="720"/>
|
|
22
|
-
|
|
23
|
-
The native **"Add workspace" / "Select workspace"** flow — a centered modal, two tabs, opens on **本机 (local)**; switch to **远程 (remote)**:
|
|
24
|
-
|
|
25
|
-
- **远程** — a **machine `<select>`**, a path field that **auto-prefills `/` and live-completes** directories (picking one immediately reveals its next level, OS/VSCode-style), plus a **浏览…** floating browser that fills the field without committing — you review, edit, then **设为远程工作区**.
|
|
26
|
-
|
|
27
|
-
Real capture (host scrubbed to a placeholder):
|
|
28
|
-
|
|
29
|
-
<img src="https://cdn.jsdelivr.net/gh/flymysql/dsh-remote@main/docs/ui-picker-panel.png" alt="dsh-remote workspace picker — real dialog; 本机 (local) tab; 远程 machine select + prefilled root path + autocomplete" width="720"/>
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## Features
|
|
34
|
-
|
|
35
|
-
- **Multi-machine SSH** — save any number of hosts (`host`/`port`/`user` + **private key** or **password**). Passwords are stored locally and never shown back in the UI. Switch with one click in Settings.
|
|
36
|
-
- **Two-tab workspace picker** (fills the native "Add workspace" flow):
|
|
37
|
-
- **本机 / Local** — opens the **native OS folder chooser** over the host, or lets you type a local path → adopted directly as a normal DSH local workspace (local workspaces fully coexist). The chooser uses the DSH `directoryPicker` service when available and otherwise falls back to the plugin's own native picker (macOS `osascript` / Linux `zenity`→`kdialog`) — so it works even when the framework service isn't registered on the desktop boot path.
|
|
38
|
-
- **远程 / Remote** — the picker is a **centered modal** (never squeezed into a narrow sidebar). Pick a **machine** → the path field is **pre-filled with `/`** and live **autocompletes** directories; **selecting a directory immediately lists its next level** (OS/VSCode-style cascade). A **浏览…** floating browser (opaque, height-capped, scrollable, follows symlinks) fills the field without committing — you review, edit, then confirm. On confirm it creates a **real local mirror** under `$DSH_HOME/remote-workspaces/<host>-<user>-<port>/<base>` (a short path-hash is appended only when a different remote path already took the same basename) that passes `fs.realpath` → the harness adopts it as a real workspace while dsh-remote keeps it synced over SFTP. The chosen workspace is persisted on the machine, so it survives restarts.
|
|
39
|
-
- **Bidirectional SFTP sync** — `rw_sync` (remote → mirror) and `rw_push` (mirror → remote) round-trip your local-mirror edits back to the machine. Both are **incremental**: files whose size + mtime already match are skipped, and a per-file size cap prevents accidental big-binary downloads. Directory sweeps run with bounded parallelism.
|
|
40
|
-
- **Model tools** — `rw_info`, `rw_connect`, `rw_pick_workspace`, `rw_list_dir`, `rw_read_file`, `rw_write_file`, `rw_exec` (runs in the current workspace by default, or `cwd=<path>`), `rw_search` (portable recursive grep), `rw_download`, `rw_upload`, `rw_sync`, `rw_push`, `rw_disconnect`.
|
|
41
|
-
- **Write directly to a remote file** — `rw_write_file` creates or overwrites a remote file (making parent directories), so you don't have to round-trip through a local mirror for a single-file edit. `rw_download` / `rw_upload` move a single file either way when you need the real bytes.
|
|
42
|
-
- **Connection health** — a **「测试连接」 test-connection** button in the Settings page validates host/user/key/password before you save a machine.
|
|
43
|
-
- The active `user@host:/path` is injected into every system prompt so the agent knows its working root.
|
|
44
|
-
- **No official `dsh-workspace` core is modified** — everything is delivered as a normal plugin (directory-flow holes filled by the client half at `priority -100`).
|
|
45
|
-
- **Cross-platform remotes** — commands use portable POSIX forms (`ls -la`, `sed -n`, `find … -exec grep`), so the same plugin works against macOS/BSD as well as GNU/Linux hosts.
|
|
46
|
-
- **Host-key verification (TOFU)** — every SSH connect verifies the host key
|
|
47
|
-
(`hostKeyMode: accept-new`): first connect records it, a later CHANGE is rejected
|
|
48
|
-
as a possible man-in-the-middle. `verify` also refuses hosts never seen before;
|
|
49
|
-
`off` disables it. Stored at `$DSH_HOME/remote-workspaces/known_hosts.json`; reset
|
|
50
|
-
with `/remote forget-key`.
|
|
51
|
-
- **Data lives under the harness home** — machines + mirrors follow `$DSH_HOME` (the desktop app sets it to its own `userData/harness`); pre-0.6 data under `~/.dsh/remote-workspaces` is migrated automatically on first run.
|
|
52
|
-
|
|
53
|
-
## Install
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
dsh plugin add dsh-remote # add the bundle
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
#
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
##
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
1
|
+
**English** · [中文](./README.zh.md)
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# dsh-remote
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/dsh-remote)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://github.com/topics/dsh-plugin)
|
|
10
|
+
|
|
11
|
+
**Remote-work assistant for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH).**
|
|
12
|
+
|
|
13
|
+
Manage several SSH machines, then pick a **remote workspace** (or a **local** one) and let the agent operate right there without leaving the harness — listing files, reading code, running builds & commands over the remote host, and keeping that remote directory mirrored into a real local workspace object.
|
|
14
|
+
|
|
15
|
+
The harness Web UI intentionally binds `127.0.0.1` (the CLI rejects `--host 0.0.0.0` for safety). This plugin goes the other way: **you connect out** to the machines you maintain, pick a workspace, and work in it through the normal DSH workspace + agent fs flows — no changes to `dsh-workspace` or the harness core.
|
|
16
|
+
|
|
17
|
+
## Screen previews
|
|
18
|
+
|
|
19
|
+
Settings → **远程工作区** — a multi-machine SSH registry (add / edit / delete / set-current, password stored locally):
|
|
20
|
+
|
|
21
|
+
<img src="https://cdn.jsdelivr.net/gh/flymysql/dsh-remote@main/docs/ui-settings-panel.png" alt="dsh-remote settings — multi-machine registry (light theme, host scrubbed)" width="720"/>
|
|
22
|
+
|
|
23
|
+
The native **"Add workspace" / "Select workspace"** flow — a centered modal, two tabs, opens on **本机 (local)**; switch to **远程 (remote)**:
|
|
24
|
+
|
|
25
|
+
- **远程** — a **machine `<select>`**, a path field that **auto-prefills `/` and live-completes** directories (picking one immediately reveals its next level, OS/VSCode-style), plus a **浏览…** floating browser that fills the field without committing — you review, edit, then **设为远程工作区**.
|
|
26
|
+
|
|
27
|
+
Real capture (host scrubbed to a placeholder):
|
|
28
|
+
|
|
29
|
+
<img src="https://cdn.jsdelivr.net/gh/flymysql/dsh-remote@main/docs/ui-picker-panel.png" alt="dsh-remote workspace picker — real dialog; 本机 (local) tab; 远程 machine select + prefilled root path + autocomplete" width="720"/>
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- **Multi-machine SSH** — save any number of hosts (`host`/`port`/`user` + **private key** or **password**). Passwords are stored locally and never shown back in the UI. Switch with one click in Settings.
|
|
36
|
+
- **Two-tab workspace picker** (fills the native "Add workspace" flow):
|
|
37
|
+
- **本机 / Local** — opens the **native OS folder chooser** over the host, or lets you type a local path → adopted directly as a normal DSH local workspace (local workspaces fully coexist). The chooser uses the DSH `directoryPicker` service when available and otherwise falls back to the plugin's own native picker (macOS `osascript` / Linux `zenity`→`kdialog`) — so it works even when the framework service isn't registered on the desktop boot path.
|
|
38
|
+
- **远程 / Remote** — the picker is a **centered modal** (never squeezed into a narrow sidebar). Pick a **machine** → the path field is **pre-filled with `/`** and live **autocompletes** directories; **selecting a directory immediately lists its next level** (OS/VSCode-style cascade). A **浏览…** floating browser (opaque, height-capped, scrollable, follows symlinks) fills the field without committing — you review, edit, then confirm. On confirm it creates a **real local mirror** under `$DSH_HOME/remote-workspaces/<host>-<user>-<port>/<base>` (a short path-hash is appended only when a different remote path already took the same basename) that passes `fs.realpath` → the harness adopts it as a real workspace while dsh-remote keeps it synced over SFTP. The chosen workspace is persisted on the machine, so it survives restarts.
|
|
39
|
+
- **Bidirectional SFTP sync** — `rw_sync` (remote → mirror) and `rw_push` (mirror → remote) round-trip your local-mirror edits back to the machine. Both are **incremental**: files whose size + mtime already match are skipped, and a per-file size cap prevents accidental big-binary downloads. Directory sweeps run with bounded parallelism.
|
|
40
|
+
- **Model tools** — `rw_info`, `rw_connect`, `rw_pick_workspace`, `rw_list_dir`, `rw_read_file`, `rw_write_file`, `rw_exec` (runs in the current workspace by default, or `cwd=<path>`), `rw_search` (portable recursive grep), `rw_download`, `rw_upload`, `rw_sync`, `rw_push`, `rw_disconnect`.
|
|
41
|
+
- **Write directly to a remote file** — `rw_write_file` creates or overwrites a remote file (making parent directories), so you don't have to round-trip through a local mirror for a single-file edit. `rw_download` / `rw_upload` move a single file either way when you need the real bytes.
|
|
42
|
+
- **Connection health** — a **「测试连接」 test-connection** button in the Settings page validates host/user/key/password before you save a machine.
|
|
43
|
+
- The active `user@host:/path` is injected into every system prompt so the agent knows its working root.
|
|
44
|
+
- **No official `dsh-workspace` core is modified** — everything is delivered as a normal plugin (directory-flow holes filled by the client half at `priority -100`).
|
|
45
|
+
- **Cross-platform remotes** — commands use portable POSIX forms (`ls -la`, `sed -n`, `find … -exec grep`), so the same plugin works against macOS/BSD as well as GNU/Linux hosts.
|
|
46
|
+
- **Host-key verification (TOFU)** — every SSH connect verifies the host key
|
|
47
|
+
(`hostKeyMode: accept-new`): first connect records it, a later CHANGE is rejected
|
|
48
|
+
as a possible man-in-the-middle. `verify` also refuses hosts never seen before;
|
|
49
|
+
`off` disables it. Stored at `$DSH_HOME/remote-workspaces/known_hosts.json`; reset
|
|
50
|
+
with `/remote forget-key`.
|
|
51
|
+
- **Data lives under the harness home** — machines + mirrors follow `$DSH_HOME` (the desktop app sets it to its own `userData/harness`); pre-0.6 data under `~/.dsh/remote-workspaces` is migrated automatically on first run.
|
|
52
|
+
|
|
53
|
+
## Install
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
dsh plugin add dsh-remote # add the bundle
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
One command installs everything: since **v0.7.2** the sidebar
|
|
60
|
+
([dsh-better-sidebar](https://www.npmjs.com/package/dsh-better-sidebar)) is a
|
|
61
|
+
hard dependency and is mounted automatically — the 🌐 remote-file explorer and
|
|
62
|
+
remote file viewer show up in the sidebar with no extra step. If you already
|
|
63
|
+
have the sidebar installed on its own, the embedded copy backs off (no double
|
|
64
|
+
mount).
|
|
65
|
+
|
|
66
|
+
> **Requires the profile's pnpm linker to be `hoisted`** (the DSH profile
|
|
67
|
+
> default, `nodeLinker: hoisted` in `pnpm-workspace.yaml`). The loader resolves
|
|
68
|
+
> plugin packages from the profile root, so the sidebar must be reachable in
|
|
69
|
+
> the top-level `node_modules`. If your `pnpm-workspace.yaml` was rewritten
|
|
70
|
+
> without `nodeLinker: hoisted`, add it back (`nodeLinker: hoisted`) and run
|
|
71
|
+
> `pnpm install` once — otherwise the embedded sidebar row fails with
|
|
72
|
+
> `Cannot find package 'dsh-better-sidebar'`.
|
|
73
|
+
|
|
74
|
+
(or `npm install dsh-remote` + add `- id: dsh-remote / name: dsh-remote` in `cordis.patch.yml`).
|
|
75
|
+
|
|
76
|
+
## Quick start
|
|
77
|
+
|
|
78
|
+
1. **Add a machine** — Settings → 远程工作区 → add host/port/user + key or password → (optional) set it current.
|
|
79
|
+
2. **Open a workspace** — click **Add workspace** in the sidebar / conversation:
|
|
80
|
+
- **本机** → system folder chooser (or type a local path) → local workspace.
|
|
81
|
+
- **远程** → choose the machine → browse to a remote directory (or type `/path`) → "设为远程工作区" ⇒ a local mirror workspace is created and adopted.
|
|
82
|
+
3. **Work with the agent** — treat it like any workspace:
|
|
83
|
+
- `rw_list_dir(path?)`/`rw_read_file` — inspect remote files
|
|
84
|
+
- `rw_write_file(path, content)` — create or overwrite a remote file directly
|
|
85
|
+
- `rw_search(pattern, path?)` — grep remote files
|
|
86
|
+
- `rw_exec(command, cwd?)` — run remote shell commands (defaults to the workspace dir)
|
|
87
|
+
- `rw_sync` / `rw_push` — pull/push the local mirror to and from the remote
|
|
88
|
+
|
|
89
|
+
## CLI defaults (optional)
|
|
90
|
+
|
|
91
|
+
Provide a default machine in `cordis.patch.yml`:
|
|
92
|
+
|
|
93
|
+
```yaml
|
|
94
|
+
# Example only — use values for your own machine.
|
|
95
|
+
- id: dsh-remote
|
|
96
|
+
name: dsh-remote
|
|
97
|
+
config:
|
|
98
|
+
host: 203.0.113.10 # or your real host / hostname
|
|
99
|
+
port: 22
|
|
100
|
+
username: dev
|
|
101
|
+
privateKeyPath: ~/.ssh/id_rsa
|
|
102
|
+
# or password: '…'
|
|
103
|
+
workspace: ~/project
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
If `host` is empty the plugin starts disconnected and you configure machines in the UI.
|
|
107
|
+
|
|
108
|
+
## CLI quick reference
|
|
109
|
+
|
|
110
|
+
Installing and driving DSH may live in different shells, so both the `dsh` binary and the `npx` form are shown. Always tell DSH **which profile** to use with `--profile <name>` (usually `web`).
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# install the bundle into a profile (npm is pulled by pnpm; recommended)
|
|
114
|
+
dsh plugin --profile web add dsh-remote
|
|
115
|
+
# same but when `dsh` is not on PATH (e.g. Windows PowerShell inside a repo)
|
|
116
|
+
npx --yes @deepseek-ai/dsh plugin --profile web add dsh-remote
|
|
117
|
+
|
|
118
|
+
# confirm it is installed wire
|
|
119
|
+
dsh plugin --profile web list
|
|
120
|
+
npx --yes @deepseek-ai/dsh plugin --profile web list
|
|
121
|
+
|
|
122
|
+
# start the web surface (reload profile; the plugin activates on boot)
|
|
123
|
+
dsh --profile web
|
|
124
|
+
npx --yes @deepseek-ai/dsh --profile web # http://127.0.0.1:3080
|
|
125
|
+
|
|
126
|
+
# use a local checkout instead of the npm version (dev iteration)
|
|
127
|
+
npx --yes @deepseek-ai/dsh plugin --profile web add /path/to/dsh-remote
|
|
128
|
+
npx --yes @deepseek-ai/dsh plugin --profile web remove dsh-remote # back to release
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
After a successful start, `Settings → 远程工作区` appears and the "Add workspace" flow gains the 本机 / 远程 tabs (screenshots above).
|
|
132
|
+
|
|
133
|
+
## Development (sandbox, not product)
|
|
134
|
+
|
|
135
|
+
Iterate **in the sandbox**, never by hand-editing a product profile — the
|
|
136
|
+
product profile is re-managed by the plugin manager and reverts hand-deployed
|
|
137
|
+
files on reinstall. Use the helper script:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
scripts/dev-run.sh --restart # start / restart the isolated sandbox
|
|
141
|
+
scripts/dev-run.sh --stop # stop it
|
|
142
|
+
scripts/dev-run.sh --status # is it running?
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
- Runs its own DSH instance (`dev-harness/harness` inside this repo) with the
|
|
146
|
+
plugin copied in from `lib/` — it boots through the same `bin.js web --patch`
|
|
147
|
+
path as the desktop app, so the sandbox reproduces the product boot behavior.
|
|
148
|
+
- The sandbox web UI serves on `http://127.0.0.1:50599` and the plugin routes
|
|
149
|
+
are live immediately (e.g. `GET /dsh-remote/machines`).
|
|
150
|
+
- **Host-half changes** (`lib/index.js`) need a sandbox restart (`--restart`);
|
|
151
|
+
**client-half changes** (`lib/client.js`) need a page refresh.
|
|
152
|
+
- Node ESM resolves dependencies from the importing file's real path, so the
|
|
153
|
+
script **copies** `lib/` (hardlink copy, `cp -al`) into the sandbox profile
|
|
154
|
+
instead of symlinking — a symlink breaks `@deepseek-ai/*` resolution.
|
|
155
|
+
- Run `scripts/check.mjs` (static framework-constraint gate: command-name
|
|
156
|
+
regex, …) before every commit; `scripts/boot-smoke.sh` boots an isolated
|
|
157
|
+
instance to prove the plugin still starts.
|
|
158
|
+
- Full rules live in `scripts/dev-standards.md` (command names, cordis service
|
|
159
|
+
access via `ctx.get()` only, optional framework services may never register,
|
|
160
|
+
verify third-party callback contracts against the real runtime, …).
|
|
161
|
+
|
|
162
|
+
Deploying to a product profile is a separate, explicit action (`./sync.sh`)
|
|
163
|
+
and should be done only when you intend to release.
|
|
164
|
+
|
|
165
|
+
## Configuration
|
|
166
|
+
|
|
167
|
+
| Key | Type | Default | Meaning |
|
|
168
|
+
| --- | --- | --- | --- |
|
|
169
|
+
| `host` | string | `''` | default SSH host (else start disconnected) |
|
|
170
|
+
| `port` | int | `22` | default SSH port |
|
|
171
|
+
| `username` | string | `''` | default SSH user |
|
|
172
|
+
| `password` | string | `''` | default SSH password (non-empty overrides key) |
|
|
173
|
+
| `privateKeyPath` | string | `''` | private key path (used only when explicitly provided) |
|
|
174
|
+
| `workspace` | string | `''` | default remote workspace path |
|
|
175
|
+
| `commandTimeoutMs` | int | 20000 | per remote command timeout |
|
|
176
|
+
| `connectTimeoutMs` | int | 15000 | SSH connect timeout |
|
|
177
|
+
| `maxFileBytes` | int | 52428800 | skip mirroring files larger than this (0 = no cap) |
|
|
178
|
+
| `hostKeyMode` | string | `accept-new` | host-key policy: `accept-new` (TOFU), `verify` (reject unknown hosts), `off` (skip) |
|
|
179
|
+
|
|
180
|
+
## Safety
|
|
181
|
+
|
|
182
|
+
Giving the plugin a machine's credentials lets the agent run **shell commands as your user** on that host. Only add machines you trust. Passwords are saved on the local machine file; treat it as sensitive (you may lock file ACLs).
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT
|
|
187
|
+
|
|
188
|
+
## Changelog
|
|
189
|
+
|
|
175
190
|
See [CHANGELOG.md](./CHANGELOG.md).
|