dsh-plugin-file-manager
面向 DeepSeek Harness(DSH) Web 界面的会话文件管理器插件。它在会话标题栏增加“文件”入口,打开后展示该会话工作区的文件树、Git 状态,并支持直接预览文本、图片和视频。
功能
- 会话感知:使用当前会话的
sessionId在 Host 端解析其固定cwd,切换会话时自动关闭旧面板,不接受浏览器传入任意目录。 - 会话路径接管:点击会话历史里的产物、最终回复内联文件引用,以及 Read/Edit/Write 工具行路径时,不再交给 DSH 调用本机默认应用,而是直接打开本插件的浏览器预览。
- 按层文件树:首次只读取工作区根目录,点击目录时才请求其直接子项;单层超过 500 项时可继续分页加载。已加载节点支持按名称或相对路径筛选,且不跟随符号链接。
- 独立预览窗口:预览、目录列表和 Git 状态使用彼此独立的请求;即使大型项目的文件树或 Git 状态仍在加载或失败,会话历史中的文件仍可直接预览。从侧栏打开时则保留文件树与 Git 变更视图。蒙层与弹窗均有柔和的淡入淡出过渡。
- 文本与代码预览:点击普通文件即可查看 UTF-8 内容;常见源码、配置与标记文件使用 DSH
CodeBlock/Shiki 语法高亮并支持复制,普通文本保持原样显示。Markdown 默认渲染为阅读预览,可在“预览 / 源代码”间切换。空文件有明确提示,超过 512 KB 时仅显示安全截断的前部内容。 - 图片预览:支持 PNG、JPEG、GIF、WebP、AVIF、BMP 和 ICO,最大 50 MB。
- 视频预览:使用浏览器原生播放器预览 MP4、M4V、MOV 和 WebM,加载后自动播放,最大 2 GB,并支持 HTTP Range 拖动与续播。
- Git 变更视图:通过独立标签页展示已修改、已暂存、新增、删除、重命名、未跟踪和冲突文件,并保留完整变更数量摘要;为避免阻塞浏览器,路径列表最多展示前 5,000 项并明确提示。
- 删除项可见:已被 Git 记录但已从磁盘删除的文件仍会以删除线节点显示。
- 大目录保护:默认隐藏
.git与node_modules,不再递归扫描整个项目,也不预读或排序完整大目录;Host 通过短期单次游标每次只读取下一页(最多 500 项),超出部分由“加载更多”继续读取。 - 安全执行: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 页面一次。进入任意带工作区的会话,标题栏右侧会出现“文件”按钮。
使用
- 打开一个已有工作区的会话。
- 点击会话标题栏的“文件”。
- “文件树”视图中的目录默认全部折叠;点击目录行时按需读取直接子项,单层超过 500 项时点击“加载更多”。存在 Git 变更的目录会显示黄色圆点。
- 切换到“Git 变更”视图,可集中查看变更文件及其状态;超过 5,000 项时保留完整计数,但路径列表只展示前 5,000 项。
- 点击普通文件会在居中的大型弹窗中打开文本、代码、图片或视频预览;代码文件按扩展名高亮,Markdown 默认显示渲染结果并可切换源代码,视频可使用原生控制条播放和拖动。
- 也可直接点击会话历史中的产物 chip、最终回复内联文件引用或 Read/Edit/Write 工具路径;路径位于工作区外时,只要它已在当前会话历史中明确出现也可预览。插件只打开独立预览,不会同时展开文件侧栏。
- 点击弹窗关闭按钮、弹窗外遮罩或按
Esc关闭预览,侧栏中的当前视图和搜索状态保持不变。 - 在搜索框输入文件名或相对路径筛选当前视图;文件树搜索范围是当前已加载节点,Git 标签页搜索已返回的变更路径。侧栏和预览弹窗各自提供刷新按钮。
Git 状态徽标采用两列 porcelain 语义:M· 表示暂存区修改,·M 表示工作区修改,?? 表示未跟踪。悬停徽标可查看中文说明。
HTTP 接口
Host 半包注册四个同源只读接口:
GET /file-manager/directory.json?sessionId=<当前会话 ID>&path=<相对目录>&cursor=<不透明分页游标>
GET /file-manager/git.json?sessionId=<当前会话 ID>
GET /file-manager/content.json?sessionId=<当前会话 ID>&path=<工作区路径或会话引用绝对路径>
GET|HEAD /file-manager/media?sessionId=<当前会话 ID>&path=<工作区路径或会话引用绝对路径>
目录、Git 和预览接口互不等待。目录接口只列出指定目录的直接子项,每页最多 500 项;path 为空表示工作区根目录,响应中的单次不透明游标用于读取下一页。Git 响应保留完整计数并将路径明细限制为 5,000 项。接口只接受当前 Host sessions 服务中存在的会话,并从不可变的 session.header.cwd 解析工作区。工作区相对路径和工作区内绝对路径执行目录边界、.git、node_modules 与符号链接校验;工作区外绝对路径必须以完整路径形式明确存在于该会话的事件数据中,并通过按事件数量失效的授权缓存。外部路径不扩展文件树,也不能授权同名前缀或后缀文件。文本接口最多携带前 512 KB UTF-8 内容;媒体接口使用同一个已校验文件句柄检查格式并流式输出,视频支持单段 bytes Range。所有响应都设置 Cache-Control: no-store,媒体额外设置 nosniff 与同源资源策略。
项目结构
src/
├── index.ts # Host 入口、会话校验与 HTTP 路由
├── content.ts # 安全文件打开、有界文本读取与编码校验
├── media.ts # 媒体签名检测、大小限制与 Range 解析
├── session-paths.ts # 会话历史绝对路径授权与缓存
├── git.ts # Git porcelain v2 调用与解析
├── tree.ts # 单层目录读取、分页与路径校验
├── types.ts # Host/Client 共享 JSON 类型
└── client/
├── index.tsx # Client Slot 注册与样式生命周期
├── components.tsx # 标题栏入口、按需文件树与独立预览
├── tree-data.ts # 目录分页合并与 Git 状态覆盖
├── history-links.ts # 会话历史路径识别与浏览器预览接管
├── language.ts # 代码文件扩展名与高亮语言映射
├── 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 Cordis 硬依赖:
slots。 - Client 平台模块:
@deepseek-ai/dsh-client-ui-primitives,复用其CodeBlock/Shiki 高亮器。 - 标题栏入口:
conversation.session.header.actions,occupant id 为file-manager。 - 浮层:
shell.overlay,occupant id 为file-manager-panel。
两个 Slot 都是 additive 且 replaceRisk: none,不会覆盖 DSH 自带界面。当前 DSH 尚未提供 openPath 前置拦截器,因此会话路径接管通过随 Client Fiber 卸载的 capture listener 识别明确的文件按钮;普通 Markdown 文本不会被猜测为路径。升级 DSH 后若会话按钮 DOM 合同变化,应同步复核 history-links.ts。
License
MIT
还没有评论,来写第一条。