dsh-file-explorer
English | 中文
DSH Web 的文件浏览器。页面边缘有一个浮动「文件」按钮,点击打开左侧抽屉(工作区文件树),点文件在右侧浮出可拖拽/缩放的预览框。点击会话区"生成的文件"芯片或工具行文件链接,会自动在预览框中打开对应文件,而非跳到系统默认应用。
截图
| 浅色 | 深色 |
|---|---|
|  |  |
功能
1. 浮动入口:页面左侧边缘固定一个「文件」按钮。它默认收起为小巧低调的把手,刻意不引人注目、不干扰主工作区;悬停或点击时展开,即可开关文件浏览器抽屉。 2. 左抽屉:左侧全高抽屉(fixed),标题栏带刷新 + 关闭按钮,内含工作区文件树。 3. 文件浏览:懒加载目录树,跟随当前会话的工作区根目录,切换会话时自动刷新;树顶有搜索框(按名称或路径即时过滤已加载条目)与排序选择器(按名称 / 大小 / 修改时间,升序或降序)。 4. 悬浮预览框:点文件在右侧浮出可拖拽/缩放/最小化/关闭的预览框。 5. 文件预览:内置文本(源码)、Markdown(渲染 + 源码切换 + 行内编辑)、图片(data URL,含 SVG)、CSV(只读表格)、二进制(hexdump)预览。 6. 可扩展预览:通过 fileExplorer 服务按扩展名注册预览器,未注册的扩展名按其检测到的类型回退到内置预览(文本→纯文本、图片→图片、二进制→十六进制);更高优先级的注册可覆盖该扩展名的内置预览。新增蛋白质结构(.cif/.pdb → Mol*)、序列等预览器无需改动核心。 7. 浏览器打开:点击 .pdf / .html / .htm / .xhtml / .json 文件直接在新浏览器标签页用浏览器原生渲染打开;HTML 页面可加载同目录资源(CSS/JS/图片/字体)。 8. 行操作菜单:hover 某一行末尾出现「···」菜单。文件行提供「打开」(或「打开为文本 / 打开为二进制」)与复制绝对/相对路径;文件与目录行都提供重命名、移动、复制、删除,目录行另增「新建文件 / 新建文件夹」。抽屉标题栏的「+ 新建」按钮可在工作区根目录创建文件或文件夹。 9. 快捷键:Ctrl/Cmd+Shift+E 开关文件浏览器抽屉。
按文件类型的预览行为
文件的打开方式取决于其扩展名及其被检测到的内容类型(文本 / 二进制):
| 类型 | 扩展名 | 默认行为 |
|---|---|---|
| 源码文本 | .ts .tsx .js .jsx .css .py .yaml .yml .sh .go .rs .xml .sql .txt … | 源码预览;大文件分页流式加载 |
| Markdown | .md .mdx | 渲染后的 HTML,可切换源码并行内编辑 |
| 图片 | .png .jpg .jpeg .gif .webp .svg | 图片预览(data URL) |
| CSV | .csv | 只读表格(首行为表头) |
.pdf | 浏览器原生阅读器,新标签页 | |
| HTML | .html .htm .xhtml | 浏览器原生渲染,新标签页 |
| JSON | .json | 浏览器原生查看,新标签页 |
| 二进制 / 未注册 | — | 十六进制转储(hexdump -C 风格,读取前 maxBinaryBytes 字节) |
文本与二进制由 NUL 字节扫描判别,图片按扩展名识别;空文件显示状态提示,超过大小上限的文件显示「文件过大」(文本改为分页而非报错)。任何文件还可在其「···」行菜单中强制「以文本打开」或「以二进制打开」,从而跳过上表的默认行为。
覆盖内置预览器
内置预览器以优先级 0 注册。由于 registerPreview(ext, component, priority) 按最高优先级优先解析,扩展可以为特定扩展名替换任意内置预览——例如更丰富的 Markdown 或 CSV 渲染器——而无需改动核心。
安装
从 git 仓库安装(推荐):
dsh plugin --profile web add github:wolfsonliu/dsh-file-explorer
dsh web或从本地目录安装:
git clone https://github.com/wolfsonliu/dsh-file-explorer
cd dsh-file-explorer
npm install
npm run build
dsh plugin --profile web add .
dsh web可选预览插件
安装额外的预览器以获得更丰富的文件预览体验:
# 基于 CodeMirror 6 的代码预览,支持语法高亮与编辑
dsh plugin --profile web add github:wolfsonliu/dsh-file-explorer-preview-code
# 基于 Mol* 的分子结构预览(.cif / .pdb)
dsh plugin --profile web add github:wolfsonliu/dsh-file-explorer-preview-molstar
# 基于 SeqViz 的序列查看器(FASTA / GenBank / JBEI / SnapGene / SBOL)
dsh plugin --profile web add github:wolfsonliu/dsh-file-explorer-preview-sequence配置
组合包默认启用以下配置:
- insert:
- id: file-explorer
name: '@dsh-external/dsh-file-explorer'
config:
maxTextBytes: 2097152
maxImageBytes: 10485760
maxBinaryBytes: 65536
maxRawBytes: 104857600
showHidden: true| 配置项 | 默认值 | 说明 |
|---|---|---|
maxTextBytes | 2 MiB | 可预览的单个文本文件大小上限 |
maxImageBytes | 10 MiB | 可预览的单个图片大小上限 |
maxBinaryBytes | 64 KiB | 二进制文件 hexdump 读取的字节数上限 |
maxRawBytes | 100 MiB | raw 动作 / readRawFile 单次读取上限(非总大小) |
showHidden | true | 是否列出以点开头(隐藏)的文件 |
inlineCsp | none | 可选:静态路由 inline html/xhtml/svg 响应的 Content-Security-Policy |
数据层
宿主半部通过 ctx.webServer.register() 注册一个 /file-explorer/api 精确路由,动作(action 查询参数):
list:列出一级目录(目录在前、按名称排序),返回BrowserEntry[]。preview:读取单个文件,返回判别式FilePreview(text/text-large/image/empty/binary/too-large)。pdf:以内联方式流式返回.pdf文件(Content-Type: application/pdf),由浏览器原生阅读器在新标签页渲染。resolve-path:解析工作区相对路径为绝对路径与父路径。write:把 UTF-8 文本写入工作区文件(POST body{ path, content }),返回保存的相对路径。
所有路径经 inside(root, input) 工作区包含校验(含 realpath 符号链接解析),越界路径一律拒绝。文本/二进制通过 NUL 字节扫描判别,图片按扩展名映射 MIME 并返回 data URL。二进制预览返回前 maxBinaryBytes 字节的 base64(附带 truncated 标志),用于 hexdump -C 风格的十六进制转储。
宿主还注册了一条 kind: 'prefix' 路由 /file-explorer/files/<sessionId>/<相对路径…>,以浏览器原生内容类型(text/html、text/css、image/*、application/pdf、字体、音视频,未知类型回退 application/octet-stream)流式返回工作区文件;支持 Range,目录回退其 index.html,并始终携带 x-content-type-options: nosniff 与 cache-control: no-store。.pdf/.html/.htm/.xhtml 即在新标签页打开该 URL。
Model Experience
本插件为纯 UI 表面,不产生任何会话事件、不改动会话日志,对模型不可见。宿主半部仅读取文件内容用于浏览器预览,与 agent 工具执行互不影响。
Known Limitations and Deferred Work
- 轻量文本编辑:内置编辑覆盖 Markdown 以及未被扩展预览认领的任何文本文件(行内编辑/保存,切换文件或关闭面板时自动保存);全文件类型的富 CodeMirror 编辑(语法高亮、行号)仍需
preview-code扩展。 - 单文件预览:无多标签页、无行内 diff。
- 自动刷新采用防抖轮询:抽屉打开且标签页可见时,目录树每约 3 秒及窗口获得焦点时重新拉取其已加载目录;没有服务器推送(
fs.watch)通道。 - 文件链接拦截为 best-effort:依赖 DSH 会话区的 CSS 类名(
_fileLink、data-produced-files-row),上游 UI 结构调整时需同步选择器。 - 大文件:超大文本文件分页流式加载(超过
maxTextBytes后经readRawFile分页预览);图片读取受maxImageBytes上限约束,二进制 hexdump 只读取前maxBinaryBytes字节。 - 隐藏文件默认显示:以点开头的文件/目录默认会列出(组合包设置
showHidden: true);如需隐藏,请在组合包配置中设置showHidden: false。 - 搜索为纯客户端:树顶搜索框只匹配已加载(已展开)的条目,位于未展开目录中的文件不会命中;当前没有服务端递归搜索。
开发扩展
dsh-file-explorer 通过 cordis 服务 fileExplorer 暴露注册入口:registerPreview、registerFileAction、writeFile 和 readRawFile。领域专家可把扩展做成独立插件(命名 @dsh-external/dsh-file-explorer-preview-<domain>),无需改动核心。
完整指南请参阅 [开发 dsh-file-explorer 扩展](docs/developing-extensions.zh.md)([English](docs/developing-extensions.md))——契约、路由、用 readRawFile 处理大文件/二进制、用 writeFile 编辑、打包、国际化,以及参考实现。
快速骨架:
import type { PreviewProps } from '@dsh-external/dsh-file-explorer/client'
export const inject = ['fileExplorer']
export function apply(ctx: {
fileExplorer: { registerPreview(ext: string, comp: React.ComponentType<PreviewProps>, priority?: number): () => void }
effect(cb: () => (() => void), label?: string): void
}): void {
ctx.effect(() => ctx.fileExplorer.registerPreview('cif', CifPreview, 10))
}扩展
dsh-file-explorer 通过 fileExplorer 服务支持扩展。已有的扩展:
| 扩展 | 说明 | 仓库 |
|---|---|---|
dsh-file-explorer-preview-code | 基于 CodeMirror 6 的代码预览与编辑 | wolfsonliu/dsh-file-explorer-preview-code |
dsh-file-explorer-preview-molstar | 基于 Mol* 的分子结构预览(.cif / .pdb) | wolfsonliu/dsh-file-explorer-preview-molstar |
dsh-file-explorer-preview-sequence | 基于 SeqViz 的序列查看器预览(FASTA / GenBank / JBEI / SnapGene / SBOL) | wolfsonliu/dsh-file-explorer-preview-sequence |
欢迎增加更多扩展——参照 [开发扩展](docs/developing-extensions.zh.md) 自行开发即可。
开发
npm install
npm run check # tsc 类型检查
npm test # vitest 单元测试
npm run build # tsc + tsdown(宿主 ESM + 客户端 CJS bundle)参考
- dsh-side-panel — 一个 DSH Web 侧边栏插件,本项目的宿主路由与文件链接拦截借鉴了它的架构。
- DeepSeek Harness — 本插件所扩展的 DSH 框架。
许可
[MIT](LICENSE)