Skip to content

Releases: xiray-xia/dsh-remote-vs

v0.8.9

Choose a tag to compare

@xiray-xia xiray-xia released this 26 Oct 01:56

修复

  • 「在终端中打开」曾在错误的远程主机上开终端(面板按上一次使用过的宿主打开),现在按搜索所属工作区的主机打开,并把顶部主机下拉同步过去。

优化点

  • 文件名搜索结果新增右键菜单:复制绝对路径、复制相对路径、打开文件所在位置、在终端中打开。
  • 打开文件所在位置会逐级展开到该文件所在目录并滚动到对应行;在终端中打开会新开标签并自动 cd 到该目录。

安装

dsh plugin --profile web add dsh-remote-vs

安装后重启 dsh web。


Fixes

  • "Open in terminal" could open the shell on the WRONG remote host (the panel reused whatever host was last used); it now opens on the host the searched workspace belongs to and moves the host picker with it.

Improvements

  • File-name results gained a right-click menu: copy absolute path, copy relative path, open containing folder, open in terminal.
  • "Open containing folder" expands every level down to the file's directory and scrolls its row into view; "open in terminal" opens a new tab that cds into that directory.

Install

dsh plugin --profile web add dsh-remote-vs

Restart dsh web after installing.

v0.8.8

Choose a tag to compare

@xiray-xia xiray-xia released this 25 Oct 01:00

修复

  • 无。

优化点

  • 并排差异的工具栏新增「上一处 / 下一处改动」按钮与 n/N 计数:跳到该处改动第一行,两端环绕;手动滚动时计数同步。
  • 工作区在侧栏的显示名改为新建时填写的名称(别名 > 名称),路径末段只作为没有名称时的回退。

安装

dsh plugin --profile web add dsh-remote-vs

安装后重启 dsh web。


Fixes

  • None.

Improvements

  • The side-by-side diff toolbar gained previous/next change buttons with an n / N counter: jumps to that change's first row, wraps at both ends, and stays in step when you scroll by hand.
  • A workspace now shows in the sidebar under the name you gave it when creating it (alias > name); the last path segment is only a fallback when no name was given.

Install

dsh plugin --profile web add dsh-remote-vs

Restart dsh web after installing.

v0.8.7

Choose a tag to compare

@xiray-xia xiray-xia released this 23 Oct 00:58

修复

  • 搜索结果点击后打开的是文件本身(内容命中会定位到该行),不再打开一个可能显示"没有差异"的空白 diff;双击同样有效。
  • 并排差异遇到很长的行时,现在可以左右滚动。

优化点

  • 顶部横向滚动条只在真的有行超出窗口时出现,加高、提高对比度并带说明提示;两个面板各自也保留可见的横向滚动条。

安装

dsh plugin --profile web add dsh-remote-vs

安装后重启 dsh web。


Fixes

  • Clicking a search result now opens the file itself (positioned at the match line for content hits) instead of a diff that could render as "no differences"; double-click works the same way.
  • Very long lines in the side-by-side diff can now be scrolled horizontally.

Improvements

  • The top horizontal scrollbar appears only when a line really overflows the view, is taller, has a stronger thumb and explains itself; each pane also keeps its own visible horizontal scrollbar.

Install

dsh plugin --profile web add dsh-remote-vs

Restart dsh web after installing.

v0.8.6

Choose a tag to compare

@xiray-xia xiray-xia released this 22 Oct 08:09

修复

  • 无。

优化点

  • 源码注释与界面占位符改为通用描述,不再出现任何具体主机、工作区或项目名。

安装

dsh plugin --profile web add dsh-remote-vs

安装后重启 dsh web。


Fixes

  • None.

Improvements

  • Source comments and the directory-picker placeholder now use generic wording; no specific host, workspace or project name appears anywhere in the published package.

Install

dsh plugin --profile web add dsh-remote-vs

Restart dsh web after installing.

v0.8.5

Choose a tag to compare

@xiray-xia xiray-xia released this 22 Oct 07:44

修复

  • 文件名搜索在深层目录里找不到文件(旧实现给搜索加了深度上限)。

优化点

  • 搜索优先使用 ripgrep,未安装时自动回退到 find / grep。
  • 开发期自检脚本不再随仓库分发。

安装

dsh plugin --profile web add dsh-remote-vs

安装后重启 dsh web。


Fixes

  • File-name search could not find files in deep directories (the previous implementation capped the search depth).

Improvements

  • Search prefers ripgrep and falls back to find / grep when it is not installed.
  • Development self-check scripts are no longer distributed with the repository.

Install

dsh plugin --profile web add dsh-remote-vs

Restart dsh web after installing.

v0.8.3 — 上架 npm / published to npm

Choose a tag to compare

@xiray-xia xiray-xia released this 22 Oct 06:00

0.8.3 — 上架 npm:dsh plugin --profile web add dsh-remote-vs

现在有两条安装路径,都不需要放行任何构建脚本:

dsh plugin --profile web add dsh-remote-vs

(npm,推荐;也可以直接跟仓库装:dsh plugin --profile web add github:xiray-xia/dsh-remote-vs。)

npm 这条路连 clone 都省了,所以更推荐。两条路能免掉"放行构建脚本"的原因是同一个:安装树里
没有任何带生命周期脚本的包 —— 包本身没有 prepare/postinstall,ssh2 是打进产物的而不是依赖。

实测(一次性 profile,跑完即删):dsh plugin --profile npmprobe add dsh-remote-vs → exit 0,
自动记入依赖并加入该 profile 的 bundles,allowBuilds 一个条目都不需要。

注意下载量:包里带着预编译 helper(vendor/dsh-remote-helpers/,约 45 MB),所以首次安装约 48 MB。
它是唯一的 helper 投放渠道(官方 Release 不带 helper 可执行文件),去掉就没法给新主机部署。

安装 / 升级

dsh plugin --profile web add dsh-remote-vs

装完重启 dsh web。


0.8.3 — on npm: dsh plugin --profile web add dsh-remote-vs

There are now two install routes, and neither needs build-script approval:

dsh plugin --profile web add dsh-remote-vs

(from npm, recommended; installing straight from the repository also works:
dsh plugin --profile web add github:xiray-xia/dsh-remote-vs.)

The npm route skips the clone entirely, so it is the one to prefer. Both routes avoid the "allow the
printed build scripts" step for the same reason: nothing in the installed tree carries a lifecycle
script — the package has no prepare/postinstall, and ssh2 is bundled into the artifact rather
than depended on.

Measured on a throwaway profile (deleted afterwards): dsh plugin --profile npmprobe add dsh-remote-vs exits 0, records the dependency and adds the plugin to that profile's bundles, with no
allowBuilds entry at all.

Mind the download size: the package carries the prebuilt helper (vendor/dsh-remote-helpers/,
~45 MB), so the first install is about 48 MB. It is the only channel that delivers a helper (the
official releases ship no helper executable), and dropping it would leave new hosts undeployable.

Install / upgrade

dsh plugin --profile web add dsh-remote-vs

Restart dsh web afterwards.

v0.8.2 — 一条命令装完(不再放行构建脚本)/ one-command install

Choose a tag to compare

@xiray-xia xiray-xia released this 21 Oct 10:54

0.8.2 — 一条命令装完,不再放行构建脚本

以前 dsh plugin --profile web add github:xiray-xia/dsh-remote-vs 在全新 profile 上会先失败,
提示你去该 profile 的 pnpm-workspace.yaml 里放行构建脚本再重跑。根因是 pnpm 12 的硬策略门:
任何带生命周期脚本的包都要求安装方先表态,未表态直接报错 —— 我们自己的 git 依赖 prepare 报
ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED,传递依赖 ssh2 / cpu-features 报 ERR_PNPM_IGNORED_BUILDS。
而策略只从安装方(workspace 根)读,依赖侧无法豁免(实测无效:dependenciesMeta: {built:false}、
--allow-build 的四种 key 形态、PNPM_CONFIG_STRICT_DEP_BUILDS=false)。

所以这一版把安装树里的构建脚本清零:

  • lib/ 入库(构建产物随仓库发布),去掉 prepare —— github: 安装拿到的就是可直接用的插件;
  • ssh2 从依赖变成产物的一部分(降为 devDependency,用 noExternal 打进宿主构建)——
    它带 install: node install.js,还拖着可选原生件 cpu-features。两者都是可选加速,
    上游失败时自己 exit 0,所以走纯 JS 加密路径。

实测(临时 profile,跑完即删):只做第一条仍被 ssh2/cpu-features 拦住;两条都做后,
同一条命令 exit 0,allowBuilds 一个条目都不需要,装出来的 lib/ 与仓库逐文件一致(98/98)。

顺带修掉一个"加载即死":把 ssh2 打进 ESM 产物后,宿主半 import 时直接
ReferenceError: __dirname is not defined(ssh2 的 CJS 在模块顶层读 __dirname),
靠 tsdown 的 shims: true 修好。这类问题 tsc、打包器、文件存在性检查都看不见,因此补了两张回归网:
scripts/verify-lib.mjs(pnpm check 第一步:入口齐全 / 已入库 / 真的能加载)与
.spike/ssh2-smoke.mjs(真机四步:连接+认证 / exec / PTY / SFTP 往返)。

安装 / 升级

dsh plugin --profile web add github:xiray-xia/dsh-remote-vs

装完重启 dsh web。


0.8.2 — one command, no build-script approval

On a fresh profile the install used to fail first and ask you to allow build scripts in that profile's
pnpm-workspace.yaml before re-running. The cause is pnpm 12's hard policy gate: any package carrying a
lifecycle script
needs the installer's explicit decision, and without one the run fails — our own git
dependency prepare produced ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED, and the transitive ssh2 /
cpu-features produced ERR_PNPM_IGNORED_BUILDS. That policy is read from the installing workspace
only
, so nothing on the dependency side can waive it (measured and rejected:
dependenciesMeta: {built:false}, four key forms of --allow-build,
PNPM_CONFIG_STRICT_DEP_BUILDS=false).

So this version removes every build script from the installed tree:

  • lib/ is committed (the built artifact ships with the repository) and prepare is gone — a
    github: install receives a plugin that is ready to load;
  • ssh2 is bundled into the artifact instead of being a dependency (it moves to devDependencies and
    goes through noExternal) — it carries install: node install.js plus the optional native
    cpu-features. Both are optional accelerators whose upstream script exits 0 when the native build
    fails, so the pure-JS crypto path is what ships.

Measured on a scratch profile (deleted afterwards): with only the first change it still failed on
ssh2/cpu-features; with both, the same command exits 0 with no allowBuilds entry at all, and the
installed lib/ matches the repository file for file (98/98).

Also fixed: a load-time crash. Bundling ssh2 into the ESM output made the host half throw
ReferenceError: __dirname is not defined on import (ssh2's CJS reads __dirname at module scope);
tsdown's shims: true fixes it. tsc, the bundler and a file-existence check all miss that class of
failure, so it now comes with two regression nets: scripts/verify-lib.mjs (first step of pnpm check:
entries present / committed / actually loadable) and .spike/ssh2-smoke.mjs (four real-host
steps: connect + auth / exec / PTY / SFTP round trip).

Install / upgrade

dsh plugin --profile web add github:xiray-xia/dsh-remote-vs

Restart dsh web afterwards.

v0.8.1 — 修复取消暂存没反应 / inverted stage verb fix

Choose a tag to compare

@xiray-xia xiray-xia released this 21 Oct 08:31

0.8.1 — 修复「取消暂存点了没反应」

0.8.0 引入了一个方向反转的回归:源代码管理面板里逐文件的按钮发的是相反的 git 命令 ——
暂存区的行点 × 跑的是 git add,更改区的行点 + 跑的是 git restore --staged。
两个方向都是静默的(本地那一行没有可移动的状态,随后那条限定路径校验又"同意"这个它从没动过的行),
所以既不报成功也不报失败:表现为「取消暂存点了没反应,全部取消暂存可以」以及「添加到暂存区没起作用」。
区级按钮(全部暂存 / 全部取消暂存)用的是字面量,方向一直是对的。

现在方向由具名 verb 决定(rowVerb,applyStage 收 'stage' | 'unstage' 而不是 boolean),
两条门禁断言盯着它(纯不变量 + 端到端真命令行),红证:把 rowVerb 反过来 → 2 条变红,
行按钮改回裸 boolean → 1 条变红。

同一版还包含

  • 暂存点击不再全量刷新:一次点击从 4 条仓库级命令(git add + 全量 git status + stash/branch/remote
    三个 extras)降到 1 个 verb + 1 条限定路径的 git status(250ms 窗口内合并,成本随被点路径而不随仓库
    大小)。实测 P710(.git/index 655MB):全量 status -uno 1.75s、限定路径 1.2s。
  • 未跟踪目录行可点击展开:-u normal 把未跟踪目录压成一行 dir/,现在点它发一条
    git status -uall -- dir/ 把里面的文件列出来(再点收起;展开态在下一次刷新里按该行是否仍存在保留/清理)。
  • 两条校验提示双语化:scm.stageMismatch / scm.stageUnverified,另有目录行的 scm.dirToggle。

安装 / 升级

dsh plugin --profile web add github:xiray-xia/dsh-remote-vs

改完客户端与宿主两半都要重启 dsh web(客户端包在启动时被抓进内存)。


0.8.1 — "Unstage does nothing" fixed

0.8.0 shipped a direction inversion: the per-file buttons in the Source Control panel issued the
opposite git command — × on a staged row ran git add, + on a changed row ran
git restore --staged. Both directions were silent (the local row has no state to move, and the
path-limited probe then agreed with the row it never changed), so a click reported neither success nor
failure: "unstage does nothing, unstage-all works" and "staging a file has no effect". The section-level
buttons pass literals, so they stayed correct.

The direction now comes from a named verb (rowVerb; applyStage takes 'stage' | 'unstage'
instead of a boolean) and two gate cases pin it — a pure invariant plus an end-to-end assertion on the
real command line. Red proofs: inverting rowVerb turns 2 red, a bare boolean turns 1 red.

Also in this version

  • A stage click no longer refreshes the repository: one click went from 4 repository-wide commands
    (git add + a full git status + the stash/branch/remote extras) to 1 verb + ONE path-limited
    git status
    , coalesced inside a 250 ms window, so the cost tracks the clicked paths instead of the
    repository size. Measured on P710 (.git/index 655MB): full status -uno 1.75s, path-limited 1.2s.
  • Untracked directory rows expand on click: -u normal collapses an untracked directory into one
    dir/ row; clicking it now issues one git status -uall -- dir/ to list the files inside (click
    again to collapse; an expansion survives a refresh while its row does, and is pruned when it does not).
  • The two verification notices are bilingual: scm.stageMismatch / scm.stageUnverified, plus
    scm.dirToggle for the new row hint.

Install / upgrade

dsh plugin --profile web add github:xiray-xia/dsh-remote-vs

Restart dsh web after upgrading: the client bundle is snapshotted at startup.

v0.8.0 — 会话改动审阅 / Session change review

Choose a tag to compare

@xiray-xia xiray-xia released this 20 Oct 11:37

会话改动审阅(Cursor 式)

  • 输入框上方可收纳面板:按会话统计改动,一行一个文件、文件类型图标、右侧 +a −b,与输入框左右对齐;⟳ 强制重扫
  • 点文件开在远程编辑器:整行着色 + 行内字符级差异(新增字符绿色背景,删除内容用插入式删除线 chip),左侧 gutter 标记
  • 改动点跳转:编辑器右上角悬浮 n/N ↑ ↓,快捷键 Alt+Shift+Cmd/Ctrl+↓/↑
  • 悬浮撤销:鼠标停在改动行 → 「撤销这处改动」(远端 git apply -R;上下文不匹配自动拒绝,脏标签页拒绝;撤销后光标留在原处、标记自动刷新)
  • 跟随会话工作区:跟随能力放在 store 层,侧栏没打开过也跟随;手动切换不被拉回;点改动文件不算手动
  • 仓库目录:沿用「源代码管理 → 仓库目录」的显式设置;根目录不是仓库时只在唯一候选下自动采用,多候选会明确提示去设置

改动采集改为纯只读

不再使用 git add 拍快照(在 AOSP 单体仓库上跑不完)。现在只做只读检查:git status 找改动 → 只读这些文件的内容 → 行级 diff 在本地算。同一仓库实测从"跑不完"降到 约 1.7 秒。

修复

  • 看门狗:host 调用不返回不再把面板永久卡在「正在统计」
  • 自锁:送错仓库目录曾导致 cd 失败 → 无摘要 → 每 3 秒循环;现在判不了就不发,host 也会退回会话根
  • 串台:面板摘要带上会话 id,切会话不再显示上一会话的状态
  • 同 alias 多工作区:按远程路径而不是 alias 第一项解析绑定

已知边界

  • 基线是会话起点;已跟踪文件的数字随轮次结束刷新(面板 3 秒轮询兜底)
  • 新文件(shell 创建的)靠慢扫描,单次预算最长约 3 分钟、间隔自适应,⟳ 可强制
  • 非 git 工作区 / 多仓库未指定仓库目录时,面板显示具体原因而不是空白
  • 编辑器里一敲字,改动标记即作废并提示「位置已过期」

安装 / 升级

dsh plugin --profile web add github:xiray-xia/dsh-remote-vs

升级后需重启 dsh web(host 与客户端两半都会重新加载)。


Session change review (Cursor style)

  • Collapsible panel above the composer: per-session changed files, one row per file, type icon, +a −b on the right, aligned with the input card; ⟳ forces a rescan
  • Click a file to open it in the remote editor: whole-line colouring plus intra-line character diff (added characters get a green background, removed text an inline struck-through chip) and gutter markers
  • Change navigation: floating n/N ↑ ↓ at the editor's top right, Alt+Shift+Cmd/Ctrl+↓/↑
  • Hover to revert: hover a changed line for "revert this change" (remote git apply -R; a context mismatch is refused, a dirty tab is refused; the caret stays put and the marks refresh)
  • Follows the session's workspace: the capability lives in the store, so it works with the sidebar never opened; a manual switch is never yanked back, and clicking a changed file does not count as manual
  • Repository directory: the explicit setting in Source Control wins; when the root is not a repository, a single candidate is adopted automatically and several candidates are reported instead of guessed

Change collection is now read-only

No more git add snapshots (they never finished on an AOSP monorepo). It now runs read-only checks only: git status to name the files, reads of just those files, and a line diff computed locally. Measured on the same repository: from "never finished" to about 1.7 s.

Fixes

  • Watchdog: a host call that never returns no longer freezes the panel at "computing…"
  • Self-lock: a wrong repository directory made cd fail, left no summary and repeated every three seconds; the client now refuses to guess and the host falls back to the session root
  • Cross-talk: the summary is tagged with its session, so switching sessions no longer shows the previous one's state
  • Same alias, several workspaces: bindings resolve by remote path instead of the first alias match

Known limits

  • The baseline is the session start; tracked files refresh as turns close (the panel's three-second poll is the backstop)
  • New files (created by a shell command) come from the slow scan: up to about three minutes, self-tuning cadence, ⟳ forces it
  • A non-git workspace or several repositories without a configured repository directory shows the specific reason instead of an empty panel
  • Typing in the editor invalidates the marks and says so ("positions stale")

Install / upgrade

dsh plugin --profile web add github:xiray-xia/dsh-remote-vs

Restart dsh web after upgrading — both halves reload.

v0.7.5 — 拖拽上传(含文件夹)+ 取消不再留下半个文件

Choose a tag to compare

@xiray-xia xiray-xia released this 20 Oct 02:48

中文

新功能

  1. 拖拽上传 —— 从资源管理器把文件/文件夹拖到远端文件树上即可上传:
    • 拖到文件夹行 = 进该目录;拖到文件行 = 进它所在目录;拖到空白 = 工作区根;
    • 支持文件夹递归(含空子目录),同样建出远端目录结构;
    • 不依赖 event.target:DSH 拖动时会在整窗口盖一层「文件或图片拖动到此处即可添加」遮罩,真正的 drop 目标是那层遮罩。现在按指针坐标在 window 捕获阶段接管,事件不会被输入框抢走(文件不会跑进聊天框)。
  2. 右键菜单 / 标题栏上传 —— 「上传文件…」「上传文件夹…」,落到右键的那个目录。

修复

  1. 取消上传不再留下半个文件 —— 改为原子上传:先写同目录 .part-<id> 侧文件,传输正常结束才 rename 到最终名;取消/失败/超限一律删掉侧文件,远端目录与操作前逐字节一致。覆盖时先删旧文件再 rename(SFTP v3 不允许 rename 覆盖)。
  2. 取消后主机不再"变慢/卡住" —— 取消的请求此前不会结束 Host 侧的上传 Promise,会一直占着 SFTP 槽位,导致该主机后续 stat/list 全部排队。现在取消即结束并释放。
  3. 上传条按阶段说话 —— 「正在读取拖放内容…」→「等待确认覆盖 N」→「上传 2/5 · 43% · 1.3/3.0MB · 文件名」;同名文件冲突只问一次;✕ 可取消整批(含弹窗等待阶段)。
  4. 上传条先消失再刷新 —— 之前要等上传后的 git status(巨型仓库可达 60 秒)跑完才消失,看起来像卡死。

兼容

要求 DSH 0.2.1-alpha.3 及以上(engines.dsh 门到底),实测基线 0.2.1-rc.2;helper 二进制不变。上传走新路由 POST /api/dsh-remote/upload(原始 body 流式写 SFTP,不缓冲整个文件、不受 10 MiB JSON 上限),单文件上限 2 GiB。

升级

host 半有改动(新路由 + 原子上传 + 取消释放):重启 Host,浏览器硬刷新(Ctrl+F5)。

在 Tauri 里用 DSH 的注意

应用内(WebView2)还要关掉 Tauri 的拖放拦截,否则系统拖放根本到不了页面:
WebviewBuilder/WebviewWindowBuilder::new(...).disable_drag_drop_handler()(已在 Android ADB Tool 2.0.52 中应用)。


English

Features

  1. Drag & drop upload — drop files or folders from Explorer onto the remote file tree:
    • onto a folder row it lands inside that folder, onto a file row beside it, onto empty space in the workspace root;
    • folders recurse (empty subdirectories included) and reproduce the same structure remotely;
    • it does not trust event.target: the DSH shell paints a full-screen "drop files here" overlay during a drag, so the real drop target is that overlay. The zone claims the event on window capture by POINTER POSITION, so the composer cannot swallow it (files never end up attached to the chat).
  2. Context menu / header upload — "Upload File…" and "Upload Folder…", targeting the directory that was right-clicked.

Fixes

  1. Cancelling no longer leaves a half file — uploads are atomic: bytes stream into a .part-<id> side file next to the target and are renamed into place only after the body ends; cancellation, failure or the size ceiling removes the side file, so the remote folder ends up byte-for-byte unchanged. Overwrite deletes the old target first (SFTP v3 rename refuses to clobber).
  2. A cancelled upload no longer wedges the host — the aborted request used to leave the Host's upload promise pending, holding an SFTP slot so later stat/list calls queued behind it. It now settles and releases immediately.
  3. The upload bar names its phase — "reading dropped items" → "waiting for the overwrite confirmation" → "uploading 2/5 · 43% · 1.3/3.0MB · name"; the overwrite prompt appears once per batch; ✕ cancels the whole batch including the prompt.
  4. The bar clears before the refresh — it used to stay up through the post-upload git status (up to 60s on a huge tree), which read as a hang.

Compatibility

Requires DSH 0.2.1-alpha.3 or newer (engines.dsh enforces the range); the tested baseline is 0.2.1-rc.2; the helper binary is unchanged. Uploads use the new POST /api/dsh-remote/upload route (raw body streamed into SFTP — no whole-file buffering, no 10 MiB JSON cap); one file may be up to 2 GiB.

Upgrading

The host half changed (new route, atomic upload, cancellation release): restart the Host, then hard-refresh the page (Ctrl+F5).

When DSH runs inside a Tauri app

Disable Tauri's drag-drop interception, or OS drops never reach the page:
WebviewBuilder/WebviewWindowBuilder::new(...).disable_drag_drop_handler() (applied in Android ADB Tool 2.0.52).