dsh-remote-vs 0.9.3 → 0.10.0
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 +5 -4
- package/README.md +6 -3
- package/cordis.patch.yml +10 -5
- package/lib/client.js +10 -8
- package/lib/index.js +2 -2
- package/lib/types/client/composer.d.ts +5 -1
- package/lib/types/index.d.ts +5 -0
- package/package.json +37 -37
- package/src/client/SettingsHosts.tsx +2 -1
- package/src/client/composer.ts +11 -2
- package/src/client/i18n.ts +2 -2
- package/src/client/store.tsx +2 -1
- package/src/index.ts +10 -2
package/README.en.md
CHANGED
|
@@ -37,8 +37,9 @@ dsh plugin --profile web add dsh-remote-vs
|
|
|
37
37
|
(From npm, recommended; installing straight from the repository also works:
|
|
38
38
|
`dsh plugin --profile web add github:xiray-xia/dsh-remote-vs`.)
|
|
39
39
|
|
|
40
|
-
Requires DSH `0.2.
|
|
41
|
-
baseline is `0.2.
|
|
40
|
+
Requires DSH `0.2.2-alpha.2` or newer (`engines.dsh` enforces the range; **the tested
|
|
41
|
+
baseline is `0.2.2-alpha.2`**). Older Hosts (`0.2.1-rc.2` generation) need plugin `0.9.3`: the
|
|
42
|
+
Remote preset of this version uses the `0.2.2-alpha.2` tool schema. `--profile web` selects which profile to install into —
|
|
42
43
|
this is a Web plugin, so it has to go into the profile your Web GUI runs from (`web` is
|
|
43
44
|
the common name; use your own profile's name).
|
|
44
45
|
|
|
@@ -301,7 +302,7 @@ over helper RPC (fs) / ssh2 (processes), local stays untouched; both share one H
|
|
|
301
302
|
|
|
302
303
|
- Alias dirs: `$DSH_HOME/remote-ssh/aliases/<id>` (empty shells, routing keys only), auto-registered into the native workspace list as `<server> > <base>`
|
|
303
304
|
- Routing switch (dropdown at the top of Settings → Remote hosts; underneath it is profile patch `- id: remote-vs`, `config.routingMode`, volatile, no restart):
|
|
304
|
-
`off` (
|
|
305
|
+
default `enforce` (real routing); switch to `off` (pure local passthrough) / `shadow` (logs, still local) as debugging escapes
|
|
305
306
|
- New workspace: the native "Add workspace…" entry is adopted (local/remote dual tab; remote leg = host→push→bind wizard)
|
|
306
307
|
- Presets: a `Remote` preset (bash toolset); under enforce, new remote sessions switch to it automatically (default preset only, never overrides an explicit choice)
|
|
307
308
|
- Ground truths (measured, not assumed):
|
|
@@ -319,7 +320,7 @@ over helper RPC (fs) / ssh2 (processes), local stays untouched; both share one H
|
|
|
319
320
|
Upstream never published helper binaries (all Release assets are empty), so this plugin builds its own:
|
|
320
321
|
|
|
321
322
|
- Build machine: WSL2 Ubuntu-22.04 (glibc 2.35, matching the remote targets), Node v24.21.0 + pnpm 11.28.5
|
|
322
|
-
- Sources: the `dsh-v0.2.1-alpha.2` tag (the **build baseline**: what must match is the wire protocol version, not the Host version —
|
|
323
|
+
- Sources: the `dsh-v0.2.1-alpha.2` tag (the **build baseline**: what must match is the wire protocol version, not the Host version — our protocol is still **2**, so a Host upgrade to `0.2.2-alpha.2` needs no rebuild either: the plugin intentionally stays on `dsh-ssh@0.2.1-rc.2`, and the new generation's protocol 3 is deliberately not followed — see §2.26 of the maintenance notes)
|
|
323
324
|
- Command: stock script `pnpm exec tsx scripts/build-exe-for-ssh-helper.ts --target=node24-linux-x64`
|
|
324
325
|
- Only deviation: no docker for the manylinux 2.28 rebuild, so a `DSH_GLIBC_CEILING`
|
|
325
326
|
env override was added (default stays 2.28); this build targets 2.35 (see `glibc-ceiling.patch` in the cache dir)
|
package/README.md
CHANGED
|
@@ -34,7 +34,8 @@ dsh plugin --profile web add dsh-remote-vs
|
|
|
34
34
|
|
|
35
35
|
(从 npm 装,推荐;也可以直接跟仓库装:`dsh plugin --profile web add github:xiray-xia/dsh-remote-vs`。)
|
|
36
36
|
|
|
37
|
-
要求 DSH `0.2.
|
|
37
|
+
要求 DSH `0.2.2-alpha.2` 及以上(`engines.dsh` 门到底;**当前实测基线 `0.2.2-alpha.2`**)。
|
|
38
|
+
旧 Host(`0.2.1-rc.2` 一代)请用插件 `0.9.3`:新版的 Remote 预设用了 `0.2.2-alpha.2` 的工具 schema。
|
|
38
39
|
`--profile web` 指明装进哪个 profile —— 本插件是 Web 插件,
|
|
39
40
|
必须装进 Web GUI 所用的那个(`web` 是常见命名,以你自己的 profile 名为准)。
|
|
40
41
|
|
|
@@ -266,7 +267,7 @@ helper RPC(fs)/ ssh2(进程),本地一切不变;两者同 Host、共
|
|
|
266
267
|
|
|
267
268
|
- 别名目录:`$DSH_HOME/remote-ssh/aliases/<id>`(空壳,只做路由键),自动注册进原生工作区列表,标题 `<server> > <base>`
|
|
268
269
|
- 路由开关(设置 → 远程主机页顶部下拉;底层是 profile patch `- id: remote-vs` 下 `config.routingMode`,volatile,免重启):
|
|
269
|
-
`off
|
|
270
|
+
默认 `enforce`(真路由);可切 `off`(纯直通本地)/ `shadow`(记日志仍走本地)作为排障开关
|
|
270
271
|
- 新建工作区:原生"添加工作区…"入口已接管(本地/远端双 tab;远端腿=主机→推送→绑定向导)
|
|
271
272
|
- 预设:`Remote` 预设(bash 工具集);enforce 下远端新会话自动切过去(默认预设才切,不践踏显式选择)
|
|
272
273
|
- 顶层真相(实测结论,非假设):
|
|
@@ -284,7 +285,9 @@ helper RPC(fs)/ ssh2(进程),本地一切不变;两者同 Host、共
|
|
|
284
285
|
官方从未发布 helper 二进制(Release assets 全空),本插件走自编译:
|
|
285
286
|
|
|
286
287
|
- 构建机:WSL2 Ubuntu-22.04(glibc 2.35,与目标远端一致),Node v24.21.0 + pnpm 11.28.5
|
|
287
|
-
- 源码:`dsh-v0.2.1-alpha.2` tag(**构建基线**:对齐的是 wire 协议号,不是 Host 版本号 ——
|
|
288
|
+
- 源码:`dsh-v0.2.1-alpha.2` tag(**构建基线**:对齐的是 wire 协议号,不是 Host 版本号 —— 我们用到的
|
|
289
|
+
协议号仍是 **2**,Host 升到 `0.2.2-alpha.2` 也不需要重编:插件自行停在 `dsh-ssh@0.2.1-rc.2`,
|
|
290
|
+
新 Host 那一代 `dsh-ssh` 的协议 3 我们故意不跟,差异见维护文档 §2.26)
|
|
288
291
|
- 命令:官方原脚本 `pnpm exec tsx scripts/build-exe-for-ssh-helper.ts --target=node24-linux-x64`
|
|
289
292
|
- 唯一偏离:无 docker 跑不了 manylinux 2.28 重编,加了 `DSH_GLIBC_CEILING`
|
|
290
293
|
环境覆盖(默认仍 2.28),本次以 2.35 构建(见缓存目录 `glibc-ceiling.patch`)
|
package/cordis.patch.yml
CHANGED
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
inject: [localFileReferences, remoteWorlds]
|
|
55
55
|
|
|
56
56
|
# Remote agent preset, bound to this bundle's lifecycle.
|
|
57
|
-
# Mirrored from preset-standard @ dsh 0.2.
|
|
57
|
+
# Mirrored from preset-standard @ dsh 0.2.2-alpha.2 with these diffs:
|
|
58
58
|
# 1. persona prefix reframed for remote SSH work (transparent routing);
|
|
59
59
|
# 2. tool-bash moved into an isolated shell group with our routed bash
|
|
60
60
|
# executor (stock root shell stays pwsh on Windows);
|
|
@@ -67,6 +67,12 @@
|
|
|
67
67
|
# preset) right after `tool-plugin-manager` — mirrored here for the same
|
|
68
68
|
# reason as above: a row missing from the mirror is a preset that silently
|
|
69
69
|
# loads a different toolset than stock.
|
|
70
|
+
# 0.2.2-alpha.2 note: stock dropped `tool-subagent-list-agents` (the
|
|
71
|
+
# `dsh-tool-subagent-control/list-agents` subpath is gone from the package),
|
|
72
|
+
# renamed `modelSelectionSettings` to `modelSelection` + `modelDiscovery`,
|
|
73
|
+
# and made the plugin-manager row conditional on `profileContext`. All
|
|
74
|
+
# three are mirrored here: the first one is a hard module-resolution error,
|
|
75
|
+
# the other two are schema drift.
|
|
70
76
|
- id: preset-remote
|
|
71
77
|
name: '@deepseek-ai/dsh-agent-preset'
|
|
72
78
|
config:
|
|
@@ -207,14 +213,13 @@
|
|
|
207
213
|
config:
|
|
208
214
|
- id: tool-subagent-control
|
|
209
215
|
name: '@deepseek-ai/dsh-tool-subagent-control'
|
|
210
|
-
- id: tool-subagent-list-agents
|
|
211
|
-
name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'
|
|
212
216
|
- id: tool-subagent
|
|
213
217
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
214
218
|
config:
|
|
215
219
|
provider: spawn
|
|
216
220
|
toolName: subagent
|
|
217
|
-
|
|
221
|
+
modelSelection: true
|
|
222
|
+
modelDiscovery: true
|
|
218
223
|
- id: tool-subagent-fork
|
|
219
224
|
name: '@deepseek-ai/dsh-tool-subagent'
|
|
220
225
|
config:
|
|
@@ -241,7 +246,7 @@
|
|
|
241
246
|
name: '@deepseek-ai/dsh-tool-present'
|
|
242
247
|
- id: tool-plugin-manager
|
|
243
248
|
name: '@deepseek-ai/dsh-plugin-manager/tools'
|
|
244
|
-
disabled:
|
|
249
|
+
disabled: !!js "!ctx.get('profileContext')"
|
|
245
250
|
- id: tool-plugin-market
|
|
246
251
|
name: '@deepseek-ai/dsh-plugin-market/tools'
|
|
247
252
|
disabled: true
|
package/lib/client.js
CHANGED
|
@@ -1355,7 +1355,7 @@ window.__ModuleLoader__.load({
|
|
|
1355
1355
|
"route.off": "关闭(直通本地)",
|
|
1356
1356
|
"route.shadow": "影子(记日志仍走本地)",
|
|
1357
1357
|
"route.enforce": "强制(真路由)",
|
|
1358
|
-
"route.hint": "切换即时生效并写入 profile
|
|
1358
|
+
"route.hint": "切换即时生效并写入 profile,无需重启;默认「强制(真路由)」。",
|
|
1359
1359
|
"route.saving": "保存中…",
|
|
1360
1360
|
"route.tombstones": "墓碑",
|
|
1361
1361
|
"route.aliasPath": "本地别名目录(原生工作区入口)",
|
|
@@ -1706,7 +1706,7 @@ window.__ModuleLoader__.load({
|
|
|
1706
1706
|
"route.off": "Off (local passthrough)",
|
|
1707
1707
|
"route.shadow": "Shadow (log only, still local)",
|
|
1708
1708
|
"route.enforce": "Enforce (real routing)",
|
|
1709
|
-
"route.hint": "Applies immediately and persists to the profile; no restart needed.",
|
|
1709
|
+
"route.hint": "Applies immediately and persists to the profile; no restart needed. Default: enforce (real routing).",
|
|
1710
1710
|
"route.saving": "Saving…",
|
|
1711
1711
|
"route.tombstones": "tombstones",
|
|
1712
1712
|
"route.aliasPath": "Local alias dir (native workspace entry)",
|
|
@@ -35259,7 +35259,7 @@ window.__ModuleLoader__.load({
|
|
|
35259
35259
|
const { actx, input } = resolved;
|
|
35260
35260
|
const snapshot = input.state.getSnapshot();
|
|
35261
35261
|
if (input.insertReference === void 0 || snapshot.draftRev === void 0) return false;
|
|
35262
|
-
if (snapshot.phase === "adjudicating" || snapshot.phase === "submitting") return false;
|
|
35262
|
+
if (snapshot.phase === "adjudicating" || snapshot.phase === "submitting" || snapshot.phase === "sending") return false;
|
|
35263
35263
|
before = snapshot.draftRev;
|
|
35264
35264
|
const at = appendOffset(snapshot);
|
|
35265
35265
|
if (at === void 0) return false;
|
|
@@ -35314,6 +35314,7 @@ window.__ModuleLoader__.load({
|
|
|
35314
35314
|
const { actx, input } = resolved;
|
|
35315
35315
|
const snapshot = input.state.getSnapshot();
|
|
35316
35316
|
const draft = snapshot.draft;
|
|
35317
|
+
if (snapshot.phase === "adjudicating" || snapshot.phase === "submitting" || snapshot.phase === "sending") return false;
|
|
35317
35318
|
if ((snapshot.occurrences ?? []).length > 0 || snapshot.phase === "claimed") {
|
|
35318
35319
|
const at = appendOffset(snapshot);
|
|
35319
35320
|
if (snapshot.draftRev === void 0 || at === void 0) {
|
|
@@ -38129,7 +38130,7 @@ Integer Float Double Long Int32 Int64 Uint8 uint32_t int32_t uint64_t int64_t si
|
|
|
38129
38130
|
const primary = host.querySelectorAll("[class*=\"rvs-ck-\"]").length;
|
|
38130
38131
|
const fallback = host.querySelectorAll("span[class^=\"rvs-t-\"]").length;
|
|
38131
38132
|
const count = primary > 0 ? primary : fallback;
|
|
38132
|
-
console.info(`[dsh-remote-vs] build 1028-
|
|
38133
|
+
console.info(`[dsh-remote-vs] build 1028-1532 · ${source} · colored tokens: ${count} (${propsRef.current.path})`);
|
|
38133
38134
|
propsRef.current.onTokens?.(count);
|
|
38134
38135
|
};
|
|
38135
38136
|
const armFallback = () => {
|
|
@@ -41695,7 +41696,7 @@ Integer Float Double Long Int32 Int64 Uint8 uint32_t int32_t uint64_t int64_t si
|
|
|
41695
41696
|
hosts: [],
|
|
41696
41697
|
workspaces: [],
|
|
41697
41698
|
routing: {
|
|
41698
|
-
mode: "
|
|
41699
|
+
mode: "enforce",
|
|
41699
41700
|
aliasPaths: {},
|
|
41700
41701
|
tombstones: []
|
|
41701
41702
|
},
|
|
@@ -44414,8 +44415,8 @@ Integer Float Double Long Int32 Int64 Uint8 uint32_t int32_t uint64_t int64_t si
|
|
|
44414
44415
|
}),
|
|
44415
44416
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
44416
44417
|
className: "rvs-build",
|
|
44417
|
-
title: `dsh-remote-vs build 1028-
|
|
44418
|
-
children: "1028-
|
|
44418
|
+
title: `dsh-remote-vs build 1028-1532`,
|
|
44419
|
+
children: "1028-1532"
|
|
44419
44420
|
}),
|
|
44420
44421
|
tokenCount !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
44421
44422
|
className: "rvs-build",
|
|
@@ -64559,7 +64560,8 @@ Integer Float Double Long Int32 Int64 Uint8 uint32_t int32_t uint64_t int64_t si
|
|
|
64559
64560
|
function SettingsHostsSection(_props) {
|
|
64560
64561
|
const [t] = (0, react.useState)(() => makeT(detectLang()));
|
|
64561
64562
|
const [hosts, setHosts] = (0, react.useState)([]);
|
|
64562
|
-
|
|
64563
|
+
/** Pre-load placeholder; matches the plugin's default (nforce) until the host answers. */
|
|
64564
|
+
const [mode, setMode] = (0, react.useState)("enforce");
|
|
64563
64565
|
const [version, setVersion] = (0, react.useState)("");
|
|
64564
64566
|
const [saving, setSaving] = (0, react.useState)(false);
|
|
64565
64567
|
const [error, setError] = (0, react.useState)(void 0);
|
package/lib/index.js
CHANGED
|
@@ -4006,7 +4006,7 @@ const Config = z.object({
|
|
|
4006
4006
|
"off",
|
|
4007
4007
|
"shadow",
|
|
4008
4008
|
"enforce"
|
|
4009
|
-
]).default("
|
|
4009
|
+
]).default("enforce").volatile(),
|
|
4010
4010
|
gitTimeoutMs: z.number().step(1).min(MIN_TIMEOUT_MS).max(MAX_TIMEOUT_MS).default(DEFAULT_GIT_TIMEOUT_MS).volatile(),
|
|
4011
4011
|
readTimeoutMs: z.number().step(1).min(MIN_TIMEOUT_MS).max(MAX_TIMEOUT_MS).default(DEFAULT_READ_TIMEOUT_MS).volatile()
|
|
4012
4012
|
});
|
|
@@ -4063,7 +4063,7 @@ function apply(ctx, config) {
|
|
|
4063
4063
|
const worlds = new RemoteWorlds(ctx, {
|
|
4064
4064
|
store,
|
|
4065
4065
|
pool,
|
|
4066
|
-
mode: () => readField(config?.routingMode, "
|
|
4066
|
+
mode: () => readField(config?.routingMode, "enforce")
|
|
4067
4067
|
});
|
|
4068
4068
|
ctx.provide("remoteWorlds", worlds);
|
|
4069
4069
|
ctx.effect(() => () => {
|
|
@@ -95,7 +95,11 @@ interface InputSnapshot {
|
|
|
95
95
|
draft: string;
|
|
96
96
|
draftRev?: number;
|
|
97
97
|
occurrences?: readonly OccurrenceLike[];
|
|
98
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Host submission plane. `sending` exists since DSH 0.2.2-alpha.2: an ordinary
|
|
100
|
+
* message the host has not accepted yet — the editor is read-only there too.
|
|
101
|
+
*/
|
|
102
|
+
phase?: 'plain' | 'adjudicating' | 'claimed' | 'submitting' | 'sending';
|
|
99
103
|
claim?: {
|
|
100
104
|
readonly token: string;
|
|
101
105
|
};
|
package/lib/types/index.d.ts
CHANGED
|
@@ -39,6 +39,11 @@ export interface Config {
|
|
|
39
39
|
/**
|
|
40
40
|
* P2 transparent-routing kill-switch: off = pure local passthrough;
|
|
41
41
|
* shadow = log remote decisions but execute locally; enforce = route.
|
|
42
|
+
*
|
|
43
|
+
* The DEFAULT is `enforce`: the plugin exists to execute remote workspaces
|
|
44
|
+
* remotely, and a fresh profile that silently kept executing locally was the
|
|
45
|
+
* most common "why is nothing remote" report. `off`/`shadow` stay available as
|
|
46
|
+
* explicit opt-outs for debugging and for hosts that must stay local.
|
|
42
47
|
*/
|
|
43
48
|
routingMode?: RoutingMode;
|
|
44
49
|
/** Per-command timeout for git work on a remote host (ms). */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-remote-vs",
|
|
3
3
|
"description": "VSCode-style remote development for DSH: SSH host manager (key/password), helper deploy pipeline with version check, remote file explorer + editor + terminal in dsh-better-sidebar.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.10.0",
|
|
5
5
|
"icon": "icon.svg",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"dsh",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"./locale/*.json": "./locale/*.json"
|
|
60
60
|
},
|
|
61
61
|
"engines": {
|
|
62
|
-
"dsh": ">=0.2.
|
|
62
|
+
"dsh": ">=0.2.2-alpha.2 <0.3.0"
|
|
63
63
|
},
|
|
64
64
|
"dsh": {
|
|
65
65
|
"bundle": {
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
"@codemirror/view": "^6.43.14",
|
|
123
123
|
"@deepseek-ai/dsh-fs-ssh": "0.2.1-rc.2",
|
|
124
124
|
"@deepseek-ai/dsh-ssh": "0.2.1-rc.2",
|
|
125
|
-
"@deepseek-ai/schemastery": "3.18.
|
|
125
|
+
"@deepseek-ai/schemastery": "3.18.6-alpha.1",
|
|
126
126
|
"@lezer/highlight": "1.2.3",
|
|
127
127
|
"@xterm/addon-fit": "^0.11.0",
|
|
128
128
|
"@xterm/xterm": "^6.0.0",
|
|
@@ -130,44 +130,44 @@
|
|
|
130
130
|
"zod": "4.4.3"
|
|
131
131
|
},
|
|
132
132
|
"peerDependencies": {
|
|
133
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
134
|
-
"@deepseek-ai/dsh-agent-preset": "^0.2.
|
|
135
|
-
"@deepseek-ai/dsh-bash-local": "^0.2.
|
|
136
|
-
"@deepseek-ai/dsh-file-reference": "^0.2.
|
|
137
|
-
"@deepseek-ai/dsh-fs": "^0.2.
|
|
138
|
-
"@deepseek-ai/dsh-shell": "^0.2.
|
|
139
|
-
"@deepseek-ai/dsh-spill": "^0.2.
|
|
140
|
-
"@deepseek-ai/dsh-subprocess": "^0.2.
|
|
141
|
-
"@deepseek-ai/dsh-tools": "^0.2.
|
|
133
|
+
"@deepseek-ai/cordis": "^4.0.6-alpha.1",
|
|
134
|
+
"@deepseek-ai/dsh-agent-preset": "^0.2.2-alpha.2",
|
|
135
|
+
"@deepseek-ai/dsh-bash-local": "^0.2.2-alpha.2",
|
|
136
|
+
"@deepseek-ai/dsh-file-reference": "^0.2.2-alpha.2",
|
|
137
|
+
"@deepseek-ai/dsh-fs": "^0.2.2-alpha.2",
|
|
138
|
+
"@deepseek-ai/dsh-shell": "^0.2.2-alpha.2",
|
|
139
|
+
"@deepseek-ai/dsh-spill": "^0.2.2-alpha.2",
|
|
140
|
+
"@deepseek-ai/dsh-subprocess": "^0.2.2-alpha.2",
|
|
141
|
+
"@deepseek-ai/dsh-tools": "^0.2.2-alpha.2",
|
|
142
142
|
"react": "^18.2.0",
|
|
143
143
|
"react-dom": "^18.2.0"
|
|
144
144
|
},
|
|
145
145
|
"devDependencies": {
|
|
146
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
147
|
-
"@deepseek-ai/dsh-agent": "0.2.
|
|
148
|
-
"@deepseek-ai/dsh-agent-preset-registry": "0.2.
|
|
149
|
-
"@deepseek-ai/dsh-api-remotes": "0.2.
|
|
150
|
-
"@deepseek-ai/dsh-bash-local": "0.2.
|
|
151
|
-
"@deepseek-ai/dsh-client-locale": "0.2.
|
|
152
|
-
"@deepseek-ai/dsh-client-ui-renderer": "0.2.
|
|
153
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.2.
|
|
154
|
-
"@deepseek-ai/dsh-client-ui-sidebar-right": "0.2.
|
|
155
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.2.
|
|
156
|
-
"@deepseek-ai/dsh-client-ui-workspace": "0.2.
|
|
157
|
-
"@deepseek-ai/dsh-file-reference": "0.2.
|
|
158
|
-
"@deepseek-ai/dsh-fs": "0.2.
|
|
159
|
-
"@deepseek-ai/dsh-host-directory-picker": "0.2.
|
|
160
|
-
"@deepseek-ai/dsh-host-webserver": "0.2.
|
|
161
|
-
"@deepseek-ai/dsh-llm": "0.2.
|
|
162
|
-
"@deepseek-ai/dsh-sandbox": "0.2.
|
|
163
|
-
"@deepseek-ai/dsh-session": "0.2.
|
|
164
|
-
"@deepseek-ai/dsh-shell": "0.2.
|
|
165
|
-
"@deepseek-ai/dsh-spill": "0.2.
|
|
166
|
-
"@deepseek-ai/dsh-subprocess": "0.2.
|
|
167
|
-
"@deepseek-ai/dsh-system-prompt": "0.2.
|
|
168
|
-
"@deepseek-ai/dsh-tools": "0.2.
|
|
169
|
-
"@deepseek-ai/dsh-working-directory": "0.2.
|
|
170
|
-
"@deepseek-ai/dsh-workspace": "0.2.
|
|
146
|
+
"@deepseek-ai/cordis": "^4.0.6-alpha.1",
|
|
147
|
+
"@deepseek-ai/dsh-agent": "0.2.2-alpha.2",
|
|
148
|
+
"@deepseek-ai/dsh-agent-preset-registry": "0.2.2-alpha.2",
|
|
149
|
+
"@deepseek-ai/dsh-api-remotes": "0.2.2-alpha.2",
|
|
150
|
+
"@deepseek-ai/dsh-bash-local": "0.2.2-alpha.2",
|
|
151
|
+
"@deepseek-ai/dsh-client-locale": "0.2.2-alpha.2",
|
|
152
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.2.2-alpha.2",
|
|
153
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.2.2-alpha.2",
|
|
154
|
+
"@deepseek-ai/dsh-client-ui-sidebar-right": "0.2.2-alpha.2",
|
|
155
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.2.2-alpha.2",
|
|
156
|
+
"@deepseek-ai/dsh-client-ui-workspace": "0.2.2-alpha.2",
|
|
157
|
+
"@deepseek-ai/dsh-file-reference": "0.2.2-alpha.2",
|
|
158
|
+
"@deepseek-ai/dsh-fs": "0.2.2-alpha.2",
|
|
159
|
+
"@deepseek-ai/dsh-host-directory-picker": "0.2.2-alpha.2",
|
|
160
|
+
"@deepseek-ai/dsh-host-webserver": "0.2.2-alpha.2",
|
|
161
|
+
"@deepseek-ai/dsh-llm": "0.2.2-alpha.2",
|
|
162
|
+
"@deepseek-ai/dsh-sandbox": "0.2.2-alpha.2",
|
|
163
|
+
"@deepseek-ai/dsh-session": "0.2.2-alpha.2",
|
|
164
|
+
"@deepseek-ai/dsh-shell": "0.2.2-alpha.2",
|
|
165
|
+
"@deepseek-ai/dsh-spill": "0.2.2-alpha.2",
|
|
166
|
+
"@deepseek-ai/dsh-subprocess": "0.2.2-alpha.2",
|
|
167
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.2-alpha.2",
|
|
168
|
+
"@deepseek-ai/dsh-tools": "0.2.2-alpha.2",
|
|
169
|
+
"@deepseek-ai/dsh-working-directory": "0.2.2-alpha.2",
|
|
170
|
+
"@deepseek-ai/dsh-workspace": "0.2.2-alpha.2",
|
|
171
171
|
"@types/node": "^22.20.0",
|
|
172
172
|
"@types/react": "~18.3.1",
|
|
173
173
|
"@types/react-dom": "^18.3.5",
|
|
@@ -22,7 +22,8 @@ import { Notice, Row, hairline, optionStyle, selectStyle } from './ui.tsx'
|
|
|
22
22
|
export function SettingsHostsSection(_props: SettingsSectionOwnerProps): ReactNode {
|
|
23
23
|
const [t] = useState(() => makeT(detectLang()))
|
|
24
24
|
const [hosts, setHosts] = useState<RemoteHostSummary[]>([])
|
|
25
|
-
|
|
25
|
+
/** Pre-load placeholder; matches the plugin's default (nforce) until the host answers. */
|
|
26
|
+
const [mode, setMode] = useState<'off' | 'shadow' | 'enforce'>('enforce')
|
|
26
27
|
const [version, setVersion] = useState('')
|
|
27
28
|
const [saving, setSaving] = useState(false)
|
|
28
29
|
const [error, setError] = useState<string | undefined>(undefined)
|
package/src/client/composer.ts
CHANGED
|
@@ -100,7 +100,11 @@ interface InputSnapshot {
|
|
|
100
100
|
draft: string
|
|
101
101
|
draftRev?: number
|
|
102
102
|
occurrences?: readonly OccurrenceLike[]
|
|
103
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Host submission plane. `sending` exists since DSH 0.2.2-alpha.2: an ordinary
|
|
105
|
+
* message the host has not accepted yet — the editor is read-only there too.
|
|
106
|
+
*/
|
|
107
|
+
phase?: 'plain' | 'adjudicating' | 'claimed' | 'submitting' | 'sending'
|
|
104
108
|
claim?: { readonly token: string }
|
|
105
109
|
}
|
|
106
110
|
|
|
@@ -295,7 +299,7 @@ export function insertDraftReference(
|
|
|
295
299
|
const { actx, input } = resolved
|
|
296
300
|
const snapshot = input.state.getSnapshot()
|
|
297
301
|
if (input.insertReference === undefined || snapshot.draftRev === undefined) return false
|
|
298
|
-
if (snapshot.phase === 'adjudicating' || snapshot.phase === 'submitting') return false
|
|
302
|
+
if (snapshot.phase === 'adjudicating' || snapshot.phase === 'submitting' || snapshot.phase === 'sending') return false
|
|
299
303
|
before = snapshot.draftRev
|
|
300
304
|
const at = appendOffset(snapshot)
|
|
301
305
|
if (at === undefined) return false
|
|
@@ -346,6 +350,11 @@ export function appendToDraft(ctx: Context, sessionId: string, text: string): bo
|
|
|
346
350
|
const { actx, input } = resolved
|
|
347
351
|
const snapshot = input.state.getSnapshot()
|
|
348
352
|
const draft = snapshot.draft
|
|
353
|
+
// The host makes the editor read-only on every submission plane: a slash
|
|
354
|
+
// command being checked, a claimed command running, and (since DSH
|
|
355
|
+
// 0.2.2-alpha.2) an ordinary message waiting for the host to accept it.
|
|
356
|
+
// Writing there would either be refused or land after the send snapshot.
|
|
357
|
+
if (snapshot.phase === 'adjudicating' || snapshot.phase === 'submitting' || snapshot.phase === 'sending') return false
|
|
349
358
|
if ((snapshot.occurrences ?? []).length > 0 || snapshot.phase === 'claimed') {
|
|
350
359
|
const at = appendOffset(snapshot)
|
|
351
360
|
if (snapshot.draftRev === undefined || at === undefined) {
|
package/src/client/i18n.ts
CHANGED
|
@@ -138,7 +138,7 @@ const zh: Record<string, string> = {
|
|
|
138
138
|
'route.off': '关闭(直通本地)',
|
|
139
139
|
'route.shadow': '影子(记日志仍走本地)',
|
|
140
140
|
'route.enforce': '强制(真路由)',
|
|
141
|
-
'route.hint': '切换即时生效并写入 profile
|
|
141
|
+
'route.hint': '切换即时生效并写入 profile,无需重启;默认「强制(真路由)」。',
|
|
142
142
|
'route.saving': '保存中…',
|
|
143
143
|
'route.tombstones': '墓碑',
|
|
144
144
|
'route.aliasPath': '本地别名目录(原生工作区入口)',
|
|
@@ -494,7 +494,7 @@ const en: Record<string, string> = {
|
|
|
494
494
|
'route.off': 'Off (local passthrough)',
|
|
495
495
|
'route.shadow': 'Shadow (log only, still local)',
|
|
496
496
|
'route.enforce': 'Enforce (real routing)',
|
|
497
|
-
'route.hint': 'Applies immediately and persists to the profile; no restart needed.',
|
|
497
|
+
'route.hint': 'Applies immediately and persists to the profile; no restart needed. Default: enforce (real routing).',
|
|
498
498
|
'route.saving': 'Saving…',
|
|
499
499
|
'route.tombstones': 'tombstones',
|
|
500
500
|
'route.aliasPath': 'Local alias dir (native workspace entry)',
|
package/src/client/store.tsx
CHANGED
|
@@ -350,7 +350,8 @@ const state: State = {
|
|
|
350
350
|
error: undefined,
|
|
351
351
|
hosts: [],
|
|
352
352
|
workspaces: [],
|
|
353
|
-
|
|
353
|
+
// Pre-bootstrap placeholder: same default as the plugin config (nforce).
|
|
354
|
+
routing: { mode: 'enforce', aliasPaths: {}, tombstones: [] },
|
|
354
355
|
workspaceId: readWorkspaceId(),
|
|
355
356
|
status: undefined,
|
|
356
357
|
head: undefined,
|
package/src/index.ts
CHANGED
|
@@ -69,6 +69,11 @@ export interface Config {
|
|
|
69
69
|
/**
|
|
70
70
|
* P2 transparent-routing kill-switch: off = pure local passthrough;
|
|
71
71
|
* shadow = log remote decisions but execute locally; enforce = route.
|
|
72
|
+
*
|
|
73
|
+
* The DEFAULT is `enforce`: the plugin exists to execute remote workspaces
|
|
74
|
+
* remotely, and a fresh profile that silently kept executing locally was the
|
|
75
|
+
* most common "why is nothing remote" report. `off`/`shadow` stay available as
|
|
76
|
+
* explicit opt-outs for debugging and for hosts that must stay local.
|
|
72
77
|
*/
|
|
73
78
|
routingMode?: RoutingMode
|
|
74
79
|
/** Per-command timeout for git work on a remote host (ms). */
|
|
@@ -107,7 +112,7 @@ export interface ResolvedConfig {
|
|
|
107
112
|
export const Config = z.object({
|
|
108
113
|
announceToAgent: z.boolean().default(false).volatile(),
|
|
109
114
|
enabled: z.boolean().default(true).volatile(),
|
|
110
|
-
routingMode: z.union(['off', 'shadow', 'enforce'] as const).default('
|
|
115
|
+
routingMode: z.union(['off', 'shadow', 'enforce'] as const).default('enforce').volatile(),
|
|
111
116
|
gitTimeoutMs: z.number().step(1).min(MIN_TIMEOUT_MS).max(MAX_TIMEOUT_MS)
|
|
112
117
|
.default(DEFAULT_GIT_TIMEOUT_MS).volatile(),
|
|
113
118
|
readTimeoutMs: z.number().step(1).min(MIN_TIMEOUT_MS).max(MAX_TIMEOUT_MS)
|
|
@@ -171,7 +176,10 @@ export function apply(ctx: Context, config?: ResolvedConfig): void {
|
|
|
171
176
|
const worlds = new RemoteWorlds(ctx, {
|
|
172
177
|
store,
|
|
173
178
|
pool,
|
|
174
|
-
|
|
179
|
+
// Keep the runtime fallback equal to the schema default: a Host that hands
|
|
180
|
+
// the plugin a config object without this field must behave like a fresh
|
|
181
|
+
// profile, not like the old opt-in (`off`) behaviour.
|
|
182
|
+
mode: () => readField(config?.routingMode, 'enforce' as RoutingMode),
|
|
175
183
|
})
|
|
176
184
|
ctx.provide('remoteWorlds', worlds)
|
|
177
185
|
ctx.effect(() => () => { pool.dispose() }, 'dsh-remote-vs: pool')
|