dsh-save-button
Adds a Download button to DSH Web GUI delivery cards, so files delivered with present save straight from the browser.
Install
dsh plugin --profile web add dsh-save-button
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
dsh-save-button

[English](README.md) | 中文
在 DSH Web GUI 的交付卡片上,给「打开」按钮右边加一个「下载」按钮:模型用 present 交付的文件(打包好的
zip、报告、数据集、图片……)直接通过浏览器下载到本机,不用再开 SFTP/SCP 拉文件。
┌──────────────────────────────────────────────────────────────────┐ │ 📄 HexHowitzer-windows-x86_64.zip ┌────────┐ │ │ 在侧边栏预览 │ 打开 ▾ │ │ ← 官方卡片 │ └────────┘ │ └──────────────────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────────────┐ │ 📄 HexHowitzer-windows-x86_64.zip ┌────────┐ ┌──────┐ │ │ 在侧边栏预览 │ 打开 ▾ │ │ ⬇ 下载│ │ ← 装上本插件 │ └────────┘ └──────┘ │ └──────────────────────────────────────────────────────────────────┘
远程/容器里跑 DSH(云主机、GPU 机器、WSL、内网服务器)时最有用:文件在 Host 上,浏览器在你手上,
中间只差一个按钮。
功能
- 交付卡片一键下载:
present声明的每个文件右边都有「下载」,走Content-Disposition: attachment,
由浏览器自己的下载管理器流式落盘——几十上百 MB 的 zip 不会先塞进页面内存。
- 官方卡片能力保留:点卡片/「打开」在侧边栏预览;右侧
▾仍是官方的「用默认应用打开」
「打开所在文件夹 / 在 Finder 中显示 / 在文件资源管理器中显示」,主机没有桌面时按官方语义禁用并提示。
- 状态就地反馈:正在准备下载… / 已开始下载 / 下载失败,点击重试;打开、打开所在文件夹同样有状态与重试。
- 不干扰官方渲染:本轮文件改动 chips、多文件折叠(
全部 N 个文件/收起)等官方行为照旧;
插件的回合没有交付产物时,官方那一行完全不受影响。
- 零依赖、零构建:纯 ESM + 手写浏览器 bundle,装完即用;没有
postinstall、没有编译步骤。 - 中英双语:跟随 GUI 语言。
- **同时兼容 DSH 0.1.5-rc.\、0.1.7-rc.\、0.2.0-rc.\、0.2.1-rc.\ 与 0.2.2-rc.1**:见下方「支持的 DSH 版本」。
安装
从 npm 装进 web profile:
dsh plugin --profile web add dsh-save-button
也可以直接装 git 仓库——本包无构建步骤,lib/ 已提交:
dsh plugin --profile web add github:hanbernate/dsh-save-button
本地开发时改为链接本目录,改动后 Host 半区随 Loader 热重组合生效:
dsh plugin --profile web add /path/to/dsh-save-button
dsh 不在 PATH 上时,用你启动 Web GUI 的那份 CLI,例如:
node ~/.dsh/profiles/node_modules/@deepseek-ai/dsh/lib/bin.js \ plugin --profile web add dsh-save-button
这条命令把 dsh-save-button 追加到 profile 的 dsh.profile.bundles,并由 Loader 插入本包
cordis.patch.yml 里的那条 entry。
生效方式:
- 装完 刷新浏览器页面(浏览器半区是页面加载的 bundle,刷新才会重新拉取)。
- 若刷新后没出现按钮,重启 Web GUI:
dsh web(或你平时的启动命令)。
验证:随便让它 present 一个文件(例如先 ls 出你打包好的 zip),卡片右侧就会出现「下载」。
使用
按钮长在官方交付卡片的「打开」右侧,一文件一个:
操作 · 行为
下载 · 先 HEAD /api/download.button?sessionId=…&seq=…&index=… 探测可下载性,成功后用 <a download> 把文件交给浏览器下载管理器;文件名由 Host 的 Content-Disposition 决定
打开 · 与官方一致:在侧边栏预览该文件
▾ 菜单 · 官方动作:用默认应用打开 / 打开所在文件夹(Finder / 资源管理器);主机无桌面时禁用
失败 · 就地显示失败原因(如「该文件已不在会话中」),点击原按钮重试
多于 4 个文件 · 保留官方折叠:全部 N 个文件 / 收起
下载只接受 (sessionId, seq, index) 三元组寻址,没有 path 参数,因此只有该会话用 present 声明过的
文件能被下载;解析、越界与类型校验、分块读取全在 Host 半区。详见 [doc/architecture.md](doc/architecture.md#5-安全边界)。
支持的 DSH 版本
DSH RC · turnTail 契约 · 集成方式 · 状态
0.1.0-rc.2 … 0.1.2-rc.1 · —(无 present / workspaceFiles) · 不适用 · 不支持
0.1.5-rc.1 / rc.2 / rc.3 · chain · 按 priority: -1 认领整行并自绘卡片 · 支持(rc.3 实测 11/11)
0.1.7-rc.1 / rc.2 · list · 官方卡片原样,注入 deliverables.file.actions 下载按钮 · 支持(rc.2 实测 12/12)
0.2.0-rc.1 / rc.2 · list · 同 0.1.7:官方卡片原样,注入 deliverables.file.actions 下载按钮 · 支持(rc.2 实测 12/12)
0.2.1-rc.1 … rc.5 · list · 同 0.1.7:官方卡片原样,注入 deliverables.file.actions 下载按钮 · 支持(rc.2 / rc.5 实测 13/13)
0.2.2-rc.1 · list · 同 0.1.7:官方卡片原样,注入 deliverables.file.actions 下载按钮 · 支持(rc.1 实测 13/13 + 真机下载 E2E)
插件在初始化时按运行时实际声明选择适配器(客户端拿不到 DSH 版本号),所以同一份安装包在所有这些线上都工作。
契约清单、测试分层、逐项实测记录与换线手册见 [doc/compatibility.md](doc/compatibility.md)。
卸载
dsh plugin --profile web remove dsh-save-button
然后刷新页面。插件被移除后,官方交付卡片原样恢复——本插件不修改任何官方文件。
故障排查
现象 · 处理
卡片右侧没有「下载」 · 先刷新页面;再确认 ~/.dsh/profiles/web/package.json 的 dsh.profile.bundles 里有 dsh-save-button;仍无效则重启 dsh web
按钮出现,点了提示「下载失败,点击重试」 · 打开浏览器开发者工具看 /api/download.button?... 的响应:401/403 = 认证,404 = 该声明不在 Session 里(换了会话或事件被裁剪),422 = 不是常规文件/在工作区之外
点「打开」报「打开失败」 · Host 无桌面(纯服务器)时的正常结果;用「下载」或侧边栏预览
报 exports["./client"] must be a string · package.json 的 exports 被改坏了,跑 npm test 看守卫
改了 lib/client.js 没生效 · 刷新页面(bundle 由 Host 按 revision 提供,页面不刷新不会重拉)
文档
文档 · 内容
[doc/architecture.md](doc/architecture.md) · 工作原理、两个半区、适配器与能力探测选择器、图标能力表、安全边界、设计决策记录
[doc/compatibility.md](doc/compatibility.md) · 支持矩阵、官方契约面清单(C1–C10)、两个断点的历史、测试分层与用例、真机实测记录(V1–V37)、换线手册
[doc/development.md](doc/development.md) · 目录结构、跑测试、改完怎么生效、新增适配器的步骤、发布前检查清单、开发陷阱
License
MIT,见 [LICENSE](LICENSE)。
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::8,最后更新 2026-11-05