dsh-file-mount:文件增量挂载与重复读取去重

前言

在 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 结果返回给模型前做三分支决策:

  1. 完全覆盖:已读行范围全部在账本内,结果换成去重 marker,不重复发送正文。
  2. 部分覆盖或文件 hash 变化:缺失或改动的正文写进本次 read 工具结果(每行带 N: 行号,与原生 read 对齐);纸条只留 head-only 账本声明。
  3. 首次挂载:保留原生 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=关闭)

想少管一些文件,调 excludeGlobsmaxManagedBytes 即可;名单外或超大文件原样放行。

典型用法

经过上面的安装步骤,正常使用 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
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜