jasper-zsh
dsh-plugin-file-manager
面向 DeepSeek Harness(DSH) Web 界面的会话文件管理器插件。它在会话标题栏增加“文件”入口,打开后展示该会话工作区的文件树、Git 状态,并支持直接预览文本、图片和视频。
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 14, 2026
- Updated
- Aug 14, 2026
Introduction
dsh-plugin-file-manager
面向 DeepSeek Harness(DSH) Web 界面的会话文件管理器插件。它在会话标题栏增加“文件”入口,打开后展示该会话工作区的文件树、Git 状态,并支持直接预览文本、图片和视频。
功能
- 会话感知:使用当前会话的
sessionId在 Host 端解析其固定cwd,切换会话时自动关闭旧面板,不接受浏览器传入任意目录。 - 文件树:所有目录默认折叠,可逐级展开/折叠,并支持按名称或相对路径搜索;不跟随符号链接。
- 独立预览窗口:文件内容在居中的大型模态弹窗中展示,侧栏继续保留文件树与 Git 变更视图。
- 文本预览:点击普通文件即可查看 UTF-8 文本内容;空文件有明确提示,超过 512 KB 时仅显示安全截断的前部内容。
- 图片预览:支持 PNG、JPEG、GIF、WebP、AVIF、BMP 和 ICO,最大 50 MB。
- 视频预览:使用浏览器原生播放器预览 MP4、M4V、MOV 和 WebM,加载后自动播放,最大 2 GB,并支持 HTTP Range 拖动与续播。
- Git 变更视图:通过独立标签页集中展示已修改、已暂存、新增、删除、重命名、未跟踪和冲突文件,并保留分支与变更数量摘要。
- 删除项可见:已被 Git 记录但已从磁盘删除的文件仍会以删除线节点显示。
- 大目录保护:默认隐藏
.git与node_modules,最多读取 4,000 个节点、20 层深度;达到限制时面板会提示结果已截断。 - 安全执行:Git 通过
execFile直接调用,不经过 shell;文件读取只接受会话工作区内的相对路径,逐级拒绝符号链接和隐藏目录,不返回工作区绝对路径。文本做大小与 UTF-8 校验,媒体同时校验扩展名、magic bytes 和容器标识。
安装
需要 DSH、Node.js 与 pnpm。
pnpm install
pnpm typecheck
pnpm build
dsh plugin --profile web add "$PWD"
dsh plugin add 会把本包作为普通依赖安装到 web profile;随后把仓库中的 cordis.patch.yml 内容合并到 $DSH_HOME/profiles/web/cordis.patch.yml:
- insert:
- id: file-manager
name: dsh-plugin-file-manager
确认依赖与插件行:
dsh plugin --profile web list
dsh --profile web --dump-config
首次安装后重启 dsh web,并刷新现有 http://127.0.0.1:3080 页面一次。进入任意带工作区的会话,标题栏右侧会出现“文件”按钮。
使用
- 打开一个已有工作区的会话。
- 点击会话标题栏的“文件”。
- “文件树”视图中的目录默认全部折叠;点击目录行展开或折叠,存在 Git 变更的目录会显示黄色圆点。
- 切换到“Git 变更”视图,可集中查看所有变更文件及其状态。
- 点击普通文件会在居中的大型弹窗中打开文本、图片或视频预览;视频可使用原生控制条播放和拖动。
- 点击弹窗关闭按钮、弹窗外遮罩或按
Esc关闭预览,侧栏中的当前视图和搜索状态保持不变。 - 在搜索框输入文件名或相对路径筛选当前视图;侧栏和预览弹窗各自提供刷新按钮。
Git 状态徽标采用两列 porcelain 语义:M· 表示暂存区修改,·M 表示工作区修改,?? 表示未跟踪。悬停徽标可查看中文说明。
HTTP 接口
Host 半包注册三个同源只读接口:
GET /file-manager/tree.json?sessionId=<当前会话 ID>
GET /file-manager/content.json?sessionId=<当前会话 ID>&path=<工作区相对路径>
GET|HEAD /file-manager/media?sessionId=<当前会话 ID>&path=<工作区相对路径>
接口只接受当前 Host sessions 服务中存在的会话,并从不可变的 session.header.cwd 解析工作区。文本接口最多携带前 512 KB UTF-8 内容;媒体接口使用同一个已校验文件句柄检查格式并流式输出,视频支持单段 bytes Range。.git、node_modules、目录、符号链接和越界路径均不会被读取。所有响应都设置 Cache-Control: no-store,媒体额外设置 nosniff 与同源资源策略。
项目结构
src/
├── index.ts # Host 入口、会话校验与 HTTP 路由
├── content.ts # 安全文件打开、有界文本读取与编码校验
├── media.ts # 媒体签名检测、大小限制与 Range 解析
├── git.ts # Git porcelain v2 调用与解析
├── tree.ts # 有界文件遍历、Git 状态合并
├── types.ts # Host/Client 共享 JSON 类型
└── client/
├── index.tsx # Client Slot 注册与样式生命周期
├── components.tsx # 标题栏入口、文件树与浮层面板
├── api.ts # 同源 Host 请求
├── store.ts # 跨 Slot 面板状态
└── styles.ts # DSH Theme token 驱动样式
构建产物:
lib/index.js:Host ESM;lib/client.js:DSH lazy-CJS Client bundle;lib/client.js.map:Client sourcemap。
开发与 HMR
pnpm dev
插件 watcher 负责重建 lib/。若希望运行中的 DSH 自动替换 Host/Client Fiber,还需在当前 web profile 的 hmr 行中启用 HMR,并将本仓库 lib/ 的真实绝对路径加入 config.root。只监听构建产物可避免递归观察 node_modules;首次把新 Client 包加入 boot graph 仍需刷新页面一次,此后的 Client bundle 修改可通过 /plugins/events 的 rebuilt 事件热替换。
常用检查:
pnpm typecheck
pnpm build
curl -fsSI http://127.0.0.1:3080/plugins/dsh-plugin-file-manager/client.js
Slot 与服务
- Host 硬依赖:
sessions、webServer。 - Client 硬依赖:
slots。 - 标题栏入口:
conversation.session.header.actions,occupant id 为file-manager。 - 浮层:
shell.overlay,occupant id 为file-manager-panel。
两个 Slot 都是 additive 且 replaceRisk: none,不会覆盖 DSH 自带界面。
License
MIT