恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
DeepSeek Harness 覆写 Diff 基础有界化:`diffBasisMaxBytes` 的职责划分与描述符级安全上限实现
首页
资讯中心
/
DeepSeek Harness 覆写 Diff 基础有界化:`diffBasisMaxBytes` 的职责划分与描述符级安全上限实现
DeepSeek Harness 覆写 Diff 基础有界化:`diffBasisMaxBytes` 的职责划分与描述符级安全上限实现
发布时间:2026/9/20 3:39:52
DeepSeek Harness 覆写 Diff 基础有界化diffBasisMaxBytes的职责划分与描述符级安全上限实现【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness导读本文以 DeepSeek Harness 仓库中已实现的 Agent Note《在提供方限制覆写上下文 diff 基础》为核心剖析dsh-fs-local为覆写overwrite操作生成的上下文 diffcontextual diff基础引入的有界读取机制新增部署配置LocalFileSystem.Config.diffBasisMaxBytes默认 10 MiB在提供方侧对仅用于展示的旧文件预读施加安全上限关闭此前 result-time applied-hunk diff 架构笔记 中记录的暂缓事项。读完本文你将理解该上限为何必须落在描述符读取而非路径 stat 预检上、before: null的整文件回退如何保证写入永不因展示性预读而失败以及提供方fs-local/fs-sandbox与消费方tool-fs之间如何划分 diff 计算的职责边界。一、背景覆写展示性预读为何需要上限在 DeepSeek Harness 的文件系统能力缝capability seam中dsh-fs-local负责实现ctx.fs约定的宿主文件系统后端。当模型调用写入工具覆写一个已存在文件时提供方会在FsWriteOutcome.before字段中返回完整旧文件内容供消费方dsh-tool-fs在结果期生成覆写上下文 diffapplied-hunk diff让 UI 以 diff 卡片的形式展示这次变更到底改了什么。问题在于这个before预读仅用于展示却在旧实现中没有上限大文件被覆写时提供方可能为生成 diff 基础而分配整个旧文件到内存仅依靠覆写前较早的路径stat结果做大小检查无法真正实施上限——外部进程可以在stat与读取之间替换文件或把文件扩大即使旧文件本身很小如果替换内容新内容很大上下文 hunk 的尺寸也会趋近于替换内容本身的规模。也就是说这条尽力而为best-effort的展示路径存在演变为无上限分配的风险。本次改动正是关闭了 result-time applied-hunk diff 笔记 中记录的暂缓上限事项。二、决策提供方侧的有界 diff 基础本 Agent Note 的核心决策可以概括为提供方拥有对before基础的上限控制因为它是提供方可选提供、尽力而为的内容而 diff 的计算、保留与展示仍归消费方tool-fs所有。2.1 新配置项diffBasisMaxBytes在 fs-local 源码 中LocalFileSystem.Config新增了diffBasisMaxBytesexport interface Config { /** Base directory for relative paths. Defaults to process.cwd(). */ cwd?: string /** * Exclusive UTF-8 byte limit on each overwrite-diff side, capped by the * runtimes safe allocation/decode maximum. Defaults to 10 MiB. */ diffBasisMaxBytes?: number }类型与校验必须是不超过运行时 Buffer 分配和字符串解码上限的正安全整数。运行时上限取node:buffer常量MAX_LENGTH与MAX_STRING_LENGTH中的较小者fs-local 源码。默认值10 * 1024 * 1024即 10 MiBfs-local 源码。非法值拒绝构造LocalFileSystem时非安全整数、小于等于 0、超过运行时上限的值都会抛出fs-local: diffBasisMaxBytes must be a positive safe integer no greater than ${MAX_DIFF_BASIS_BYTES}fs-local 源码。语义它是排他exclusive上限——只有当替换内容的 UTF-8 字节数严格低于该值且为生成基础而打开的旧文件最终也低于该值时覆写才提供before。2.2 写入路径中的判定逻辑在 fs-local 的writeText实现 中可以看到完整的判定与降级流程const diffable existing ! null Buffer.byteLength(content, utf8) this.config.diffBasisMaxBytes const before diffable ? await readTextForDiff(target.targetKey, this.config.diffBasisMaxBytes, signal) : null await writeFileAtomic(...)关键点旧文件存在existing ! null且替换内容UTF-8 字节低于上限时才尝试读取基础读取本身交给readTextForDiff由它独立裁决旧文件一侧是否合格无论before是字符串还是null原子写入都会照常执行——上限只影响展示不影响提交after返回 LF 规范化后的新内容与before共用同一套换行基准避免 CRLF 覆写被误判为每一行都变化行尾恢复属于存储细节applied-hunk diff 忽略它。2.3 描述符级有界读取readTextForDiff上限的真正实施点在 fs-local 的fsio.ts中的readTextForDiff。它的设计要点是先打开文件拿到文件描述符再对描述符自身执行 stat 与分块读取从而规避路径 stat 与读取之间的 TOCTOU 窗口const handle await open(absolutePath, r) let buffer: Buffer let total 0 let openedSize 0 try { const info await handle.stat() if (!info.isFile()) return null if (info.size maxBytes) return null openedSize info.size // One extra byte detects growth after stat without retaining per-read backing buffers. buffer Buffer.allocUnsafe(openedSize 1) while (total buffer.length) { const length Math.min(buffer.length - total, DIFF_BASIS_READ_CHUNK_BYTES) const { bytesRead } await handle.read(buffer, total, length, null) if (bytesRead 0) break total bytesRead } } finally { await handle.close() }这套流程逐条落实了 Agent Note 中的约束先 open再 stat 描述符检查的是即将真正读取的那个文件对象而不是可能已被外部替换的路径描述符 stat 后大小变化也返回nulltotal ! openedSize时放弃fsio.ts即使最终大小仍低于上限——因为部分前缀会成为错误的 diff 基础误导 diff 展示多分配一个字节用于检测读取后增长Buffer.allocUnsafe(openedSize 1)让分块读取在读到边界后还能多读一字节配合total ! openedSize检查能在不保留额外缓冲的前提下发现文件在读取期间被扩大取消响应分块循环中反复检查AbortSignal取消以FS_ABORTED向上传播二进制 / 无效 UTF-8 拒绝basis.includes(0)检测 NUL 字节TextDecoder(utf-8, { fatal: true })严格解码解码失败返回nullerrno 吞并描述符阶段的任何 errno旧文件在调用方预检之后、基础读取打开之前被删除或变得不可读或读取故障都只返回null——已提交的写入绝不能因为一次展示性预读失败而失败只有取消和非 errno 故障继续向上传播。2.4 测试验证fs-local 的测试 覆盖了该配置的行为契约默认值未传配置时diffBasisMaxBytes为10 * 1024 * 1024filesystem.spec.ts非法值拒绝[0, -1, 1.5, maxDiffBasisBytes 1, Number.MAX_SAFE_INTEGER 1]等非正、小数、超上限、不安全整数都会被拒绝并抛出上述错误消息filesystem.spec.ts测试辅助函数remountWithDiffLimit通过重新挂载LocalFileSystem插件来验证不同上限下的行为filesystem.spec.ts。三、职责划分提供方与消费方各管一段本次决策最值得注意的设计是把同一条before合格规则完整地放在提供方而不是分散到两个插件中关注点归属方依据before上限配置diffBasisMaxBytes提供方dsh-fs-local/dsh-fs-sandboxfs-local 源码有界基础读取描述符级提供方dsh-fs-localfsio.tsdiff 计算、保留与展示消费方dsh-tool-fstool-fs write.ts读取路由流式阈值readStreamMinSize消费方dsh-tool-fs独立策略tool-fs read.ts3.1 消费方如何消费before: nulltool-fs的写入工具在presentationMeta中把before null直接映射为空 diff 列表绝不调用 diff 计算tool-fs write.tspresentationMeta: (args, value) ({ diffs: value.before null ? [] : computeHunkDiffs(args.file_path, value.before, value.after) .map(({ path, oldText, newText }) ({ path, oldText, newText })), }),而当before有值时computeHunkDiffstool-fs diff.ts基于diff库的structuredPatch对 LF 规范化的 before/after 逐 hunk 生成{ path, oldText, newText }结构附着在工具结果上供 UI 渲染 diff 卡片。这就是 Agent Note 中消费方使用既有的整文件回退的落地形态before: null时没有上下文 hunk但写入确认照常返回模型看到的仍是Updated确认与 diff 卡片的降级表现。3.2 与readStreamMinSize的关系diffBasisMaxBytes与tool-fs的readStreamMinSize文件读取时流式/整读的路由阈值是相互独立的配置readStreamMinSize属于消费方决定read工具对大文件走streamText还是readTexttool-fs read.tsdiffBasisMaxBytes属于提供方决定覆写展示的旧文本获取成本。Agent Note 明确否决了在提供方保留一个与读取工具流式阈值相等的硬编码阈值的替代方案理由是读取阈值可由部署配置且归消费方所有两个同值常量会形成无法强制的一致性耦合而覆写基础本身是部署层面的内存与展示选择两者无需共享数值。四、沙箱后端的继承dsh-fs-sandbox的SandboxedFileSystem直接继承LocalFileSystem其插件配置类型就是本地后端的配置原样fs-sandbox 源码/** * Plugin config: the local backends knobs verbatim (cwd resolution default * and diffBasisMaxBytes overwrite-presentation bound). The sandbox default * (mode workspace-write fallback root) is NOT here — ctx.sandboxPolicy * resolves each calling session for every enforcing capability. */ export type Config LocalConfig因此diffBasisMaxBytes对沙箱强制后端同样生效沙箱层只增加每次变更调用的策略栅栏containment 检查文本存储机制——包括有界 diff 基础读取——逐字继承自本地实现。这意味着在沙箱模式下部署同样只需设置一个配置项即可约束覆写展示的旧文本缓冲。五、部署配置示例在 fs-local README 的配置示例基础上加入新的上限配置# dsh-fs-local 插件配置 config: cwd: /absolute/path/to/workspace diffBasisMaxBytes: 10485760 # 10 MiB排他上限更小的旧文件/新内容才生成 before字段速查字段默认值含义cwdprocess.cwd()相对路径的基准目录diffBasisMaxBytes10 MiB每次覆写 diff 一侧的 UTF-8 字节上限更大的覆写返回before: null生成的配置目录参见 config-catalog是每个受支持字段及其 JSDoc 的穷尽式真源。六、被否决的替代方案为什么先 stat 再整读不可行Agent Note 记录了三个被否决的方案理解它们能更清楚为什么最终实现长这样保留与读取工具流式阈值相等的硬编码阈值否决。读取阈值可由部署配置且归消费方所有两个同值常量会形成无法强制的一致性耦合而覆写基础本身是部署层面的内存与展示选择。提供方只限制旧内容一侧在tool-fs限制新内容 diff否决。当提供方配置的成对上限已排除替换内容时这仍会先获取旧文本同时把同一条before合格规则拆到两个插件中。消费方仍可自由施加额外的输出限制。信任初次probe()的大小再执行普通整文件读取否决。该大小可能在读取前变旧描述符读取必须对它真正读取的对象实施上限——这正是readTextForDiff先open再stat的原因。至于为任意大的内容对流式生成上下文 diff本缺陷修复不采用当前文件系统 seam 返回完整的before/after字符串当前 diff 实现也消费这两个字符串流式 diff 需要独立的跨包协议与展示设计超出了本次有界化修复的范围。七、后果与权衡引入diffBasisMaxBytes后的可观察后果部署可以独立调整覆写基础成本而不必改变读取路由readStreamMinSize无关达到或超过排他上限时覆写仍会成功并通过整文件回退保持可见before: null→ 空 diff 列表但不再提供上下文 hunk低于上限时除调用方持有的替换内容外提供方仍可能持有接近diffBasisMaxBytes的旧文本例如 10 MiB 上限下约 10 MiB 的缓冲对合格覆写而言有界描述符读取增加了一次open/stat/read序列的系统调用开销同时防止陈旧的路径探测把这个序列变成无上限分配——这是本修复的核心收益。八、延伸阅读result-time applied-hunk diff 架构笔记——本次改动关闭其暂缓上限事项的上游设计文档fs-local 实现——Config、构造校验、writeText与editText的完整实现fsio.ts 有界读取——readTextForDiff的描述符级实现细节fs-local 测试——默认值、非法值拒绝与上限行为的测试契约fs-sandbox 源码——沙箱后端原样继承本地配置的证明tool-fs 写入工具——消费方对before: null的整文件回退渲染tool-fs diff 计算——computeHunkDiffs的逐 hunk 生成逻辑。【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考