🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

宿主机文件管理 mrouyang4/dsh-file-download

DeepSeek 客户端
mrouyang412 天前有提交已提供中文文档扫描:含敏感能力兼容 / 相关生态

在浏览器里浏览、上传、下载和打包宿主机文件

29.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/24 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/mrouyang4/dsh-file-download.git

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么[目录]—
生态应用
桌面端 / Web 外壳,不以 dsh plugin add 安装
暂无时间戳·判据 →
装得上吗[实装验证]—
本站尚未做安装检查
暂无时间戳·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/05·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 12 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件发起外部网络请求
查看扫描证据(共 29 处,展示前 15 条)
  • 读取本地文件
    lib/index.js:223
    out.push(await realpath(record.path));
  • 读取本地文件
    lib/index.js:248
    await access(target);
  • 读取本地文件
    lib/index.js:269
    real = await realpath(target);
  • 读取本地文件
    lib/index.js:314
    info = await stat(located.path);
  • 读取本地文件
    lib/index.js:351
    const stream = createReadStream(located.path, range ? { start, end } : undefined);
  • 读取本地文件
    lib/index.js:376
    info = await stat(located.path);
  • 写入本地文件
    lib/index.js:650
    await pipeline(Readable.fromWeb(request.body), createWriteStream(partial));
  • 写入本地文件
    lib/index.js:651
    await rename(partial, target);
  • 删除本地文件
    lib/index.js:654
    await rm(partial, { force: true });
  • 写入本地文件
    lib/index.js:704
    await mkdir(target);
  • 删除本地文件递归
    lib/index.js:720
    await rm(target.path, { recursive: true, force: true });
  • 删除本地文件递归
    lib/index.js:803
    await rm(item.path, { recursive: true, force: true });
  • 写入本地文件
    lib/index.js:893
    await rename(item.path, destination);
  • 删除本地文件递归
    lib/index.js:900
    await rm(item.path, { recursive: true, force: true });
  • 发起网络请求
    client/client.js:251
    rootsPromise ??= fetch("/api/files.roots", { headers: { accept: "application/json" } })
扫描于 2026/11/5(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

在浏览器里管理 DSH 主机上的文件:浏览、下载、上传、mkdir、ZIP、删除,还能在交付文件卡片和文档预览面板上一键下载。

README

由 DeepSeek 最新模型翻译生成
dsh-file-download 给 DSH(DeepSeek Harness)Web 加一套「在浏览器里管文件」的能力:浏览、下载、上传、新建文件夹、目录打包、永久删除,以及聊天产出卡片与右侧预览面板的一键下载。 DSH 的进程和文件都在宿主机(跑 dsh web 的那台机器)上,而浏览器经常是从另一台设备远程打开的。聊天里的文件卡片、预览面板只在宿主机上有意义——远程浏览器既打不开也拿不到。这个插件补一条同源、带登录态保护的 HTTP 通道,外加一个自带的文件管理页。 - 无需额外服务、无第三方依赖、不需要构建 - 左侧新增「文件管理」入口:两级目录(工作区 → 目录),路径不越出工作区 - 聊天里的产出卡片、⋯ 菜单、右侧预览面板都长出一个「下载到本地」 目录 - 安装 - 符合 DSH 插件规范 - 用法 - 1. 侧边栏「文件管理」 - 2. 浏览与导航 - 3. 上传 - 4. 新建文件夹 - 5. 下载单个文件 - 6. 打包整个目录 - 7. 复制直链 - 8. 删除 - 9. 产出卡片上的下载按钮 - 10. 卡片-菜单里的「下载到本地」 - 11. 右侧预览面板的下载按钮 - 12. 聊天里的下载链接 - 13. 直接拼 URL - 配置 - HTTP 路由 - 安全边界 - 故障排查 - 兼容性与已知限制 - 开发 - License 安装
展开完整文档(README 剩余 1 节)
dsh-file-download

给 DSH(DeepSeek Harness)Web 加一套「在浏览器里管文件」的能力:浏览、下载、上传、新建文件夹、目录打包、永久删除,以及聊天产出卡片与右侧预览面板的一键下载。

DSH 的进程和文件都在宿主机(跑 dsh web 的那台机器)上,而浏览器经常是从另一台设备远程打开的。聊天里的文件卡片、预览面板只在宿主机上有意义——远程浏览器既打不开也拿不到。这个插件补一条同源、带登录态保护的 HTTP 通道,外加一个自带的文件管理页。

- 无需额外服务、无第三方依赖、不需要构建
- 左侧新增「文件管理」入口:两级目录(工作区 → 目录),路径不越出工作区
- 聊天里的产出卡片、⋯ 菜单、右侧预览面板都长出一个「下载到本地」

目录

- 安装
- 符合 DSH 插件规范
- 用法
- 1. 侧边栏「文件管理」
- 2. 浏览与导航
- 3. 上传
- 4. 新建文件夹
- 5. 下载单个文件
- 6. 打包整个目录
- 7. 复制直链
- 8. 删除
- 9. 产出卡片上的下载按钮
- 10. 卡片-菜单里的「下载到本地」
- 11. 右侧预览面板的下载按钮
- 12. 聊天里的下载链接
- 13. 直接拼 URL
- 配置
- HTTP 路由
- 安全边界
- 故障排查
- 兼容性与已知限制
- 开发
- License

安装

假设 DSH 的插件目录是 ~/.dsh/plugins,Web profile 是 web。

1. 放源码

git clone https://github.com/mrouyang4/dsh-file-download.git ~/.dsh/plugins/dsh-file-download

2. 声明依赖 — ~/.dsh/profiles/web/package.json

{
"dependencies": {
"dsh-file-download": "file:/Users/you/.dsh/plugins/dsh-file-download"
}
}

file: 后面写绝对路径,不要用 $HOME(npm 不会展开变量)。

3. 挂载插件 — ~/.dsh/profiles/web/cordis.patch.yml

- insert:
- id: dsh-file-download
name: dsh-file-download

4. 让 node_modules 指到源码

ln -s ~/.dsh/plugins/dsh-file-download ~/.dsh/profiles/web/node_modules/dsh-file-download

插件没有构建步骤,软链过去就能用。

5. 重启 DSH Web,刷新页面。左侧导航出现「文件管理」,即安装成功。

之后:改 lib/ 需要重启 DSH;只改 client/client.js 刷新页面即可(客户端 bundle 每次请求重新生成,带内容哈希)。

符合 DSH 插件规范

这是一个标准 DSH 插件(Cordis 插件 + web 客户端 bundle + locale 字典),不是外挂脚本。逐条对照如下,全部可用 node scripts/conformance.mjs 复核(CI 每次 push 都会跑)。

| 规范要求 | 本插件的实现 |
| 宿主入口导出 name | lib/index.js:31 — export const name = "dsh-file-download",与包名一致 |
| 声明依赖的宿主服务 inject | lib/index.js:34 — export const inject = ["connection", "webServer"] |
| 导出 apply(ctx, config) 作为生命周期入口 | lib/index.js:528 — export function apply(ctx, config = {}) |
| 注册即受管,卸载即摘除 | 路由与页面都包在 ctx.effect(() => { ... return dispose }) 里,插件停用时自动注销 6 条 API 与 /files |
| 配置 schema(可选项) | 未声明 Config。config.roots 在 makeRoots() 内按 Array.isArray 校验,非法值退回工作区列表,不会因错误配置抛错 |
| 宿主入口声明 | package.json → main: "lib/index.js",exports["."] 指向同一文件 |
| 客户端入口声明 | exports["./client"] → client/client.js |
| web 客户端声明 | dsh.client.platform: "web";dsh.client.inject: ["@deepseek-ai/dsh-client-ui-sidebar"] 声明它扩展的是侧边栏插件 |
| 客户端 bundle 形态 | client/client.js 是 window.__ModuleLoader__.load({ id: "dsh-file-download", factory }),id 与包名一致,导出 name / apply / inject |
| 清单可被外部读取 | exports["./package.json"],便于 DSH 读取版本与 dsh 段 |
| 本地化字典 | locale/zh.json + locale/en.json,两份 meta.title / meta.description 键集一致(插件列表里的名称与说明就来自这里) |
| 宿主版本兼容声明 | peerDependencies["@deepseek-ai/cordis"]: "~4.0.5",DSH 的安装与启动版本检查以此为准 |
| 只依赖公开入口 | 宿主侧只 import node: 内置模块与本地文件,不深入 DSH 内部私有模块 |
| 鉴权围栏 | 所有 /api/ 经 connection 服务(cookie 鉴权 + Host/Origin 栅栏),/files 走 ctx.connection.requestRejection,未登录 401、跨界 403 |

自检:

node scripts/conformance.mjs # 16 项规范检查
./scripts/check.sh # 语法 + JSON + zip 冒烟 + 上面这 16 项

输出形如:

ok host.name dsh-file-download
ok host.inject connection, webServer
ok host.apply injects 2 services
ok exports["./client"] ./client/client.js
ok dsh.client.platform web
ok client loader __ModuleLoader__.load
ok locale zh + en (description,title)

符合 DSH 插件规范:16 项全部通过

用法

1. 侧边栏「文件管理」

左侧导航里点 文件管理(齿轮区,排在「自动化任务」之后)。主区打开插件自带的文件管理页。

首页是工作区列表,不是文件系统根目录:

┌ 工作区 ────────────────────────────────┐ │ 📁 AI-Job /…/Desktop/AI-Job [进入 →] │ │ 📁 default-workspace /…/default-workspace [进入 →] │ └────────────────────────────────────────┘ 只列出 DSH 的工作区目录,看不到工作区以外的路径

列表来自 DSH 的工作区注册表,新增工作区后这里会自动出现(点右上「刷新」即时更新)。

2. 浏览与导航

进入某个工作区后:

| 操作 | 位置 | 结果 |
| 进子目录 | 行尾「打开」或双击目录行 | 面包屑变成 AI-Job / _demo-office |
| 回上级 | 工具栏「↑ 上一级」 | 工作区根处按钮置灰,无法再往上 |
| 换工作区 | 工具栏「← 工作区」 | 回到工作区列表 |
| 找文件 | 工具栏「筛选当前目录…」 | 按名称实时过滤,输入 pdf 只看 PDF |
| 刷新 | 工具栏「刷新」 | 重新拉取当前目录 |

面包屑从工作区名开始,永远不会出现 /Users/... 这样的上级路径——这也是插件的路径边界在界面上的体现。

3. 上传

两种方式,都上传到当前目录:

- 点工具栏 上传文件 → 选一个或多个文件
- 直接把文件拖进页面(整页都是放置区,松手即传)

细节:

- 同名文件默认不覆盖,返回 409,界面提示已存在;需要覆盖时接口加 overwrite=1
- 先写 <文件名>.part-<随机后缀>,写完后原子改名,中途断掉不会留下半截正式文件
- 上传过程中按钮显示进度;完成后列表自动出现该文件

4. 新建文件夹

点 新建文件夹 → 输入名称 → 回车。重名返回 409 并在界面提示。

名称只能是一个路径段:/、\、..、空字节、超过 255 字符都会被拒绝(防止借名字越界)。

5. 下载单个文件

文件行尾点 下载:浏览器按宿主机的真实文件名保存(中文名正常,走 RFC 5987)。

- 大文件流式传输,支持 Range 断点
- 想在浏览器里直接看而不是下载(PDF / 图片):用「复制链接」拿到的地址后面加 &inline=1

6. 打包整个目录

- 目录行尾 打包 → 下载 <目录名>.zip
- 工具栏 打包当前目录 → 下载当前所在目录的 zip

实现是自己写的流式 STORE zip(lib/zip.js):边读边写,内存只占一个 chunk,不依赖 zip/archiver;单文件上限 4 GiB。

7. 复制直链

行尾 复制链接 把 /api/files.download?path=<绝对路径> 写入剪贴板,可以贴到任何需要的地方(比如 Markdown 里 )。链接继承浏览器登录态,未登录访问会 401。

8. 删除

行尾 删除 → 弹窗「永久删除「文件名」?」→ 点 永久删除 才执行。

- 是真删除(rm -rf),不进回收站,删完不可恢复
- 目录会连同内容一起删
- 工作区根目录本身拒绝删除

9. 产出卡片上的下载按钮

DSH 把智能体生成的文档显示成卡片(Word/Excel/PDF 图标那种)。插件在卡片右侧、预览按钮旁边加一个 ⤓ 下载 按钮:

1. 在对话里找到产出卡片
2. 点卡片右侧的 ⤓(在「预览」和 ⌄ 之间)
3. 浏览器直接下载该文件

按钮只对宿主机上真实存在的产出出现;路径取自卡片自带的信息,不额外发请求。

10. 卡片 ⋯ 菜单里的「下载到本地」

卡片右侧 ⌄ 展开的菜单,宿主原来列的是「用 WPS/Word/LibreOffice 打开」——那是给宿主机本机用的,手机端点了没意义。插件在菜单第一条插入 下载到本地,其余菜单项保持原样。

11. 右侧预览面板的下载按钮

在聊天里点开任意文件,右侧预览面板的标题栏会出现下载图标:

/report/2026Q3.docx ⟳ [WPS ⌄] ⤓
└ 当前预览的文件路径 └ 宿主工具 └ 插件加的下载

- 点 ⤓ 下载正在预览的这个文件
- 文本、代码、图片、PDF、Office 预览都生效(所有渲染器共用同一个标题栏)
- 预览的是工作区以外的文件时,点击提示「该文件不在工作区内,无法下载」,不会下载出一个 JSON 错误体

实现用的是官方槽位 sidebar.right.tab.document.actions,入参就是 { absolutePath },不是 DOM 硬改。

12. 聊天里的下载链接

DSH 会在对话里渲染 /api/files.download、/api/files.zip 这样的链接。直接点会就地下载:不跳路由、不加历史记录,对话停在原处(插件在 window 捕获阶段拦截,用隐藏 触发)。

13. 直接拼 URL

任何地方都能用,只要浏览器带着 DSH 的登录态:

下载

/api/files.download?path=/abs/path/report.docx

在浏览器里直接打开 PDF / 图片

/api/files.download?path=/abs/path/report.pdf&inline=1

换个保存名

/api/files.download?path=/abs/path/a.bin&name=汇总表.xlsx

打包目录

/api/files.zip?path=/abs/path/some-dir

path 可以是相对进程工作目录的路径,内部统一 realpath 后再做边界判定。

配置

默认根目录来自 DSH 工作区注册表(界面上「工作区」里挂的那些目录),不包含 $HOME。需要额外放开某些目录时才写 roots: yaml
- id: dsh-file-download
name: dsh-file-download
config:
roots:
- /Users/you/Downloads
- /Volumes/Data/work

写了 roots 就以你的列表为准($HOME 不会自动加入)。注册表为空时才退回进程工作目录。

HTTP 路由

| 路由 | 方法 | 说明 |
| /api/files.download?path=<绝对路径> | GET / HEAD | 流式下载,支持 Range、中文文件名(RFC 5987)、按扩展名给 Content-Type |
| /api/files.list?path=<目录> | GET | 目录列表 JSON(/files 页面的数据源) |
| /api/files.roots | GET | 可访问的工作区列表 [{path,name}] |
| /api/files.zip?path=<目录> | GET / HEAD | 目录打包,流式 STORE zip,无第三方依赖 |
| /api/files.upload?path=<目录>&name=<文件名>[&overwrite=1] | POST | 流式写入临时文件后原子改名;同名默认 409 |
| /api/files.mkdir?path=<父目录>&name=<名称> | POST | 新建文件夹;已存在 409 |
| /api/files.delete?path=<条目> | POST | 永久删除(rm -rf),拒绝删除根目录 |
| /files | GET | 自带文件管理页 |

/api/ 注册在 DSH 的 exact-Fetch 路由表上,继承浏览器 cookie 鉴权(仅 owner Peer 可用);/files 通过 ctx.connection.requestRejection 做同样的 401/403 判定。

查询参数

- path(必填):绝对路径,或相对进程工作目录的路径
- inline=1:Content-Disposition: inline,PDF/图片直接在浏览器里看
- name=...:覆盖下载保存的文件名

安全边界

1. 允许的根目录 = DSH 工作区注册表,默认不含 $HOME;realpath 之后必须落在其中,否则 403
2. 符号链接按真实路径判定,指向根外的一律拒绝
3. 上传/新建的名字只能是一个路径段(拒绝 /、\、..、空字节、>255 字符)
4. 删除是永久删除,界面二次确认,且拒绝删除根目录本身
5. 上传先写 .part-<随机> 再原子改名,失败不留半截文件
6. 所有路由都要求登录态,未登录 401;/files 同样
7. 文件操作全部走 fs/promises:某个目录在云端同步中卡住,只影响它自己那个请求,不会拖死整个 DSH 进程(同步 fs 会,见「故障排查」)

故障排查

| 现象 | 原因 / 处理 |
| 左侧没有「文件管理」 | 没挂载或没重启。检查 cordis.patch.yml 的 insert,改完必须重启 DSH Web |
| 打开是空白 / 404 | node_modules/dsh-file-download 软链没建或指错;ls -l 确认指向源码目录 |
| 点下载返回 401 | 浏览器没有登录态:用启动时打印的带 token= 的地址打开一次 DSH Web |
| 点下载返回 403 | 目标路径不在工作区内。要么把目录加成 DSH 工作区,要么写进 config.roots |
| 上传返回 409 | 同名文件已存在。改名,或接口加 overwrite=1 |
| 列表转圈很久后报「请求超时」 | 该目录在云端同步(iCloud / 网盘)中卡住;插件已把超时限制在 20 秒且不阻塞其他请求,排除同步后点「刷新」 |
| 卡片下载按钮没出现 | 宿主改版导致卡片结构变了(这部分是 DOM 增强)。刷新页面;仍不行请带上 DSH 版本提 issue |
| 预览面板没有下载图标 | 同上,属于槽位缺失;确认 DSH ≥ 0.2.x 且插件版本 ≥ 0.5.0 |
| 中文文件名乱码 | 下载响应带 filename=UTF-8'';个别老浏览器不认,用 name= 显式指定 |

兼容性与已知限制
- 在 DSH 0.2.x(Web)上开发并验证;用到 slots、connection.requestRejection、workspaceRegistry
- 无第三方依赖;lib/zip.js 是自写的流式 STORE zip 写入器
- Node 侧只用 node:fs/promises 与 node:path
- 不做缩略图/在线预览渲染,预览交给浏览器原生能力(inline=1)
- 上传是整文件单请求,没有分片/断点续传
- Range 每次独立,不保存断点状态
- 卡片按钮与卡片菜单是 DOM 增强(宿主没开放对应槽),DSH 改版时这里最可能要跟着调;其余入口都用官方槽位

开发 bash ./scripts/check.sh # 语法 + JSON + zip 写入器冒烟测试,与 CI 同一套检查

CI(.github/workflows/check.yml)在每次 push 和 PR 上跑同样的三步:node --check 四个文件、JSON 校验、zip 写入器冒烟测试(生成物断言本地文件头与中央目录)。

结构:

lib/index.js 宿主侧:路由注册、路径边界、下载/列表/打包/上传/建目录/删除 lib/page.js /files 页面(HTML + 内联 JS,两级导航、拖拽上传、二次确认) lib/zip.js 流式 STORE zip 写入器 client/client.js 客户端:侧边栏面板、卡片按钮、卡片菜单、预览面板槽位、链接拦截 locale/.json 插件列表里的标题与说明

改动生效规则:lib/ → 重启 DSH;client/client.js → 刷新页面。

License

MIT © mrouyang4
预览分享卡片长什么样 ↓mrouyang4/dsh-file-download
分享 · DeepSeek Harness Hub
mrouyang4/dsh-file-download

在浏览器里浏览、上传、下载和打包宿主机文件

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部