前言¶
在 DeepSeek Harness(DSH)里跑智能体,读文件是高频操作。同一份源码被反复 read、大文件只改了几行却要整本重发、上下文里已经出现过却还要再占 token——这些都会直接吃掉窗口预算。原生 read 工具每次返回完整正文,没有跨次调用的账本。
下面介绍社区插件 dsh-file-mount(维护者 acefun29)。它在 tools/post-execute 面拦截 read / write / edit,记录每个文件哪些行范围已进入模型上下文;重复读取只补缺失部分,磁盘改动时按行级 diff 只补变动行,并在 Web 端提供「挂载文件」仪表盘。机制移植自 piwpi 的 context-mount。
这是什么¶
dsh-file-mount 是 DSH 的双半部插件:宿主侧(dsh.bundle.patch)接管文件读写结果,浏览器侧(dsh.client manifest)渲染挂载仪表盘。当前版本 0.5.1,MIT 许可证,GitHub 约 13 stars。目录页:SkillHub;源码:github.com/acefun29/dsh-file-mount。
依赖 DSH 0.1.0-rc.5 及以上,需要本机 pnpm 和 Node ^22.19 || >=24。
核心功能¶
模型侧:增量读取与去重¶
插件在 read 结果返回给模型前做三分支决策:
- 完全覆盖:已读行范围全部在账本内,结果换成去重 marker,不重复发送正文。
- 部分覆盖或文件 hash 变化:缺失或改动的正文写进本次 read 工具结果(每行带
N:行号,与原生 read 对齐);纸条只留 head-only 账本声明。 - 首次挂载:保留原生 read 正文,同时附加账本纸条。
文件在磁盘上变化时,插件拿行级底稿做 diff,只补改动行;日志追加场景只补新尾巴。AI 通过 write 写过的完整文件,回头 read 直接免单。模型还可调用 file_mount_forget 工具主动作废某文件的账,强制下次整本重读。
write 会把整本书标记为「已知道」;edit 会使缓存失效但保留行指纹底稿,下一次读必重读盘并走行级 diff。
界面侧:挂载文件仪表盘¶
Web 端「挂载文件」标签页提供:
- 顶栏固定净节省与路径搜索,文件列表单独滚动。
- 每个文件行可展开为文件段列表,每段带新鲜度色带(绿 / 黄 / 橙 / 红 / 灰)和过期次数。
- 覆盖图用色块标出已挂载行在文件中的位置,支持搜索、排序、净节省与人民币折算。
- 对话区有上下文注入折叠行;「文件已变更」时行上有角标。
节省统计按中文 1 字 ≈ 1 token、其他 4 字符 ≈ 1 token 估算,界面显示净值(省下的减去纸条花掉的,为负时按 0 显示)。可选配置 statsFile 把跨会话总账落盘。
新鲜度与安全阀¶
挂载段记录载体消息的 seq,按其在当前上下文中的位置判断是否还适合去重。接近窗口上限时,越靠前的内容越容易被摘账;过期一次后按 pinAfter 钉住。另有重读安全阀(valveReads):连续全覆盖去重达到次数后放行原生 read。
安装与启用¶
插件以当前 DSH 进程权限运行,安装前应阅读仓库源码与 MIT 许可证。装好 profile 后必须重启 harness(刷新页面不够)。
推荐:GitHub Release¶
npx --yes @deepseek-ai/dsh plugin --profile web add https://github.com/acefun29/dsh-file-mount/releases/latest/download/dsh-file-mount.tgz
npx --yes @deepseek-ai/dsh --profile web
已有全局 dsh 时,第一行可换成:
dsh plugin --profile web add https://github.com/acefun29/dsh-file-mount/releases/latest/download/dsh-file-mount.tgz
装的是预构建包,无需 allowBuilds,也不走 npm。不要用 github:acefun29/dsh-file-mount 装源码——仓库不含 lib/,且包已去掉 prepare。
本仓库开发版¶
pnpm dsh:install
Windows 上不要对目录路径用 dsh plugin add . 或 file:E:\...(pnpm 会把盘符拼进 profile 目录,插件装上但不激活)。
配置¶
在 profile 的插件配置中加入:
- id: file-mount
name: dsh-file-mount
config:
enabled: true # 总开关;关闭后所有读取原生透传
capacity: 32 # 文件身份缓存容量(挂载中文件不受淘汰影响)
ttlMs: 300000 # 缓存安全阀:同 stat 内容被改的兜底重读间隔
maxPinnedFiles: 256 # 单个会话最多钉住多少个挂载文件
minSavedTokens: 16 # 去重/增量净收益低于此值则原生透传且不写账本
maxFingerprintBytes: 1000000 # 超过此大小的文件不留行级底稿
maxManagedBytes: 16777216 # 超过此大小的文件不接管,原样放行
excludeGlobs: ['**/node_modules/**'] # 这些路径永远原样放行
statsFile: ./dsh-file-mount-stats.json # 可选:跨会话总账落盘路径
freshnessEnabled: true # 新鲜度:默认开
pinAfter: 1 # 过期一次后钉住
contextWindow: 128000 # 会话未报告窗口时的默认 W
valveReads: 2 # 重读安全阀:连续拦截达到此次数触发原生透传重读(0=关闭)
想少管一些文件,调 excludeGlobs 和 maxManagedBytes 即可;名单外或超大文件原样放行。
典型用法¶
经过上面的安装步骤,正常使用 read / write / edit 工具即可,插件自动介入,无需额外命令。
强制重读某个文件:让模型调用 file_mount_forget 作废该文件账,下次 read 整本重发。去重 marker 也会提示:上文找不到内容时,先 forget 再 read。
查看跨会话统计:配置 statsFile 后自动累计,可通过 fileMount.stats() 读取(界面展示暂缓)。
排除不需要接管的目录:在 excludeGlobs 中加入模式,例如 ['**/node_modules/**', '**/dist/**']。
适用场景与注意¶
适合谁
- 长会话里反复读取同一份源码、配置或文档的智能体任务。
- 大文件局部改动后只需补 diff 行的场景。
- 需要在 Web 端直观看到上下文挂载状态与 token 节省估算的开发者。
已知限制
- compaction 后「已挂载」保证失效:被压缩掉的挂载内容离开模型上下文,下一次读取重新锚定。
- 增量 / 去重替换了结果文本,UI 的 read 卡片会降级为通用卡片(canonical value 完整保留)。
- 超过
maxManagedBytes的文件与excludeGlobs命中的路径不接管。 - 新鲜度是启发式:段过期不代表内容被移出上下文(只有压缩才会),过期重发是故意的 token 开销。
- 省的数字是估算,不宜当作精确计费依据。
插件与 DSH 宿主、read / write / edit 工具结构耦合;升级 DSH 后建议关注插件 Release 是否跟进。社区目录 SkillHub 是独立站点,与 DeepSeek / 幻方无官方从属关系。
结尾¶
dsh-file-mount 把文件读取从「每次全量」变成「账本 + 增量」,在重复读、局部改、长会话三类场景里都能省下上下文 token,同时用仪表盘把挂载状态可视化。若你正在 DSH 上跑代码类智能体,值得一试。
- 目录页:https://www.skillhub.cn/plugins/acefun29/dsh-file-mount
- GitHub:https://github.com/acefun29/dsh-file-mount