前言¶
做 DSH 插件开发或智能体调试时,经常需要在浏览器界面里确认宿主机上的目录结构、配置文件内容或某张图片。此前这类操作要么跳回终端敲命令,要么让插件自己实现一份文件树组件。下面介绍的插件直接在 DSH 左侧边栏加了一个文件管理面板,把宿主机的文件浏览、预览、下载和上传收进界面里。
- 插件名称:ccfeeling/dsh-host-file-explorer(npm 包名
@local/dsh-host-file-explorer,版本 1.2.0) - 维护者:ccfeeling
- 许可证:MIT
- 分类:客户端插件
- 来源:社区插件目录(非 DeepSeek / 幻方官方应用商店),GitHub 仓库为 https://github.com/ccfeeling/dsh-host-file-explorer
定位¶
这是一个标准的 DSH bundle,由 Host 半和 Client 半组成。Host 半在 ctx.hostFiles 上挂了一个服务,基于 node:fs/promises 提供七个动词;Client 半在侧边栏注册 host-files 面板,提供目录列表、文本与图片预览、文件下载、文件上传和新建文件夹,并支持十二种界面语言。
所有读取都经过 Host/Client Remote 通道——也就是智能体自身文件系统工具所使用的同一条边界——而不是绕过去直接访问文件系统。
核心功能¶
功能清单如下,全部来自 README:
- 目录列表:目录在前、文件在后,每项带类型、大小、修改时间,隐藏项以变暗样式展示。
- 文本预览:读取文本文件的前 256 KiB 并渲染;二进制文件会自行报告而不打印乱码。
- 图片预览:PNG、JPEG、GIF、WebP、AVIF、SVG 以内联方式显示,而不是按文本读取。
- 下载:通过 Harness 的认证文件路由交给浏览器,保留文件原名。
- 上传:把浏览器中的文件作为一次 Remote 调用发送到当前打开的目录,字节随命令携带,不经过浏览器文件路由。
- 新建文件夹:在当前目录下创建单段子目录。
- 路径导航:可跳转到绝对路径、返回上级,还有 HOME、tmp、cwd、文件系统根的快捷键。
安装与启用¶
有三种安装方式,按使用场景选择。
第一种是插件管理器安装(README 推荐)。先克隆仓库,再从本地路径安装:
# clone
git clone https://github.com/ccfeeling/dsh-host-file-explorer.git
# 安装到某个 DSH profile,profile 名称与路径按自己环境替换
dsh plugin --profile web add /path/to/dsh-host-file-explorer
对应的 tool call 是 plugin_manager { action: 'install_bundle', target: '<local path>' }。
第二种是从插件市场安装。该插件收录在 awesome-dsh-plugin 列表中,因此可以直接从 GitHub 安装:
dsh plugin --profile web add github:ccfeeling/dsh-host-file-explorer
第三种是作为 profile 依赖声明。编辑 ~/.dsh/profiles/<profile>/package.json:
{
"dependencies": {
"@local/dsh-host-file-explorer": "link:/abs/path/to/dsh-host-file-explorer"
}
}
安装完成后,侧边栏会在 Plugins 和 Schedules 之后出现一个文件夹图标,点击即打开面板。
一个与 profile 依赖相关的坑:如果 profile 里有会随包发布 agent skills 的依赖(例如 dsh-answer-me-with-html),pnpm 10.11+ 和 12.x 在 skills 目录未声明时会拒绝安装并抛出 ERR_PNPM_NO_AGENT_SKILLS_DIR。在该 profile 的 pnpm-workspace.yaml 里加一段即可:
skills:
dirs: []
底层架构¶
插件的代码结构如下:
index.js (Host) ctx.hostFiles —— 七个动词,基于 node:fs/promises
client.js (Client) 侧边栏入口 + 主面板 + Remote 命名空间挂载
Host 半用原型标记 @deepseek-ai/dsh-typert-protocol/remote-methods 声明 Remote 传输,让网关在 SRC 模式下能发现这些方法:
| 方法 | 参数 | 返回 |
|---|---|---|
roots() |
— | HOME、tmp、cwd、文件系统根 |
list(path, signal) |
path |
{ path, parent, home, entries[{ name, path, kind, size, modified, mime, hidden }], truncated } |
stat(path, signal) |
path |
{ path, kind, size, modified, mime } |
read(path, signal) |
path |
{ path, size, modified, binary, truncated, text } |
mkdir(path, name, signal) |
path, name |
{ path } |
upload(path, name, data, signal) |
path, name, data |
{ path, size } |
limits() |
— | 单个下载允许的最大字节数 |
这里有个签名约束:signal 必须是最后一个参数。网关用 Function.prototype.toString() 解析方法签名来推导线上参数,签名写错会导致调用失败。
关于文件如何到达浏览器:页面本身不走 Remote 通道传文件字节,而是向 Host 询问文件在 Harness 认证文件路由上的地址(与文档预览中 Markdown 图片所用的路线相同),浏览器复用页面已持有的会话去取。下载保留原名,预览拿到原始 Content-Type,所以 PNG 就按 PNG 渲染。单次响应受 Harness 附件字节上限约束(默认 20 MiB);面板会先从 Host 读取这个上限,遇到超限的下载直接拒绝并说明原因,而不是启动注定失败的传输。
Client 半手写了一个 Typert Remote 贡献,用 ctx.remote.$mount(...) 挂载,随后注册两个槽位:
sidebar.panellist:idhost-files,order30,带独立的文件夹图标;main:keyhost-files,即侧边栏按钮打开的面板。
两个开发陷阱¶
README 特别强调了两点,扩展或复制该插件时需要留意。
第一,命名空间不能声明为插件自己的 inject。挂载出来的 remote.hostFiles 是一个独立的服务,且只有在本插件挂载之后才存在;若有 fiber 去等它,会永远等不到,插件也就无法启动。要用 Cordis mixin 的入口直接从共享 store 读取:
const namespace = ctx.get('remote.hostFiles');
官方插件能写 inject: ['remote.agentPresets'],是因为有别的包挂载了那些命名空间,消费者可以直接声明依赖;本插件不能这么写,正因如此。
第二,Client 半不依赖任何 Harness client 包。它只用 react 和 zod,样式用 --dsw-alias-* 主题变量实现,没有从 @deepseek-ai/dsh-client-ui-primitives 及其同类包导入任何东西。
权限与边界¶
使用前需要明确这些限制:
- 插件以 Harness 进程自身的权限读取宿主机文件系统,账户能读到什么,它就能读到什么。这是宿主机文件浏览器的固有属性,因此只在你信任的机器和账户上启用。
- 能力范围是只读,加上新建文件夹和上传文件。它不能修改、删除或重命名已有文件,上传也从不覆盖同名文件。
- 单次列表最多返回 2000 项,单次预览最多读 256 KiB。
- 单次下载不超过 Harness 附件字节上限(默认 20 MiB),面板会在超限下载开始前说明原因。
安装第三方插件前,建议先读一遍源码和许可证(本插件为 MIT),确认下载与上传的目录范围符合预期。
小结¶
这个插件的价值在于把宿主机文件系统的操作收敛进 DSH 界面,同时复用智能体已有的 Remote 通道,不引入额外的越权路径。对于需要在 Web 端核对配置文件、查看图片或收发文件的 DSH 用户和插件开发者,它是一个可以直接安装的客户端工具。
- 目录页:https://www.skillhub.cn/plugins/ccfeeling/dsh-host-file-explorer
- GitHub:https://github.com/ccfeeling/dsh-host-file-explorer
开发阶段可以使用 README 提供的命令做基本检查:
node --check index.js
node --check client.js
npm pack --dry-run # 查看实际发布的文件列表