Files
deepseek-harness/packages/fs/tool-fs/README.zh.md
T
Tianyi Cui 10ef3d4924 docs,feat(doc-gates): fix 15 dead anchor fragments; verify-md-links now validates fragments
A corpus sweep under the doc/prose standards found 15 links whose #fragment
named no anchor in its target — reworded headings, one relocated contract
(tool-fs → the group README's no-timeout rule), and zh sides citing English
slugs their Chinese headings never produce. Fixed all 15 (zh sides get the
conventional explicit <a id> + English fragment), fixed the one generator-owned
instance at its source (gen-doc-graphs), and extended verify-md-links to
resolve fragments onto Markdown targets — same-file anchors included — against
heading slugs and explicit <a id>, so the class is gated instead of manually
grepped. Remaining probes (narrated history, duplication shingles, comment
transcripts, budgets) came back clean; sibling-adapter README symmetry and
implemented-note contrasts are deliberate keeps.
2026-08-09 10:56:42 +08:00

12 KiB
Raw Blame History

@deepseek-ai/dsh-tool-fs

English | 中文

面向模型的文件系统工具readwriteedit)及其执行器。这是文件系统栈的消费方层:拥有工具名称、JSON Schema、参数校验、提示词段、读取窗口逻辑和结果格式化。它直接通过 ctx.fs 提供方 seam@deepseek-ai/dsh-fs)读取/写入/编辑。新鲜度/观察策略由独立插件(@deepseek-ai/dsh-fs-policy)通过 fs/* 事件门禁贡献;工具不与其方法耦合。使用施加沙箱限制的提供方时,逐会话执行需要共享沙箱策略服务,工具还会为文件系统变更提供升权路径。

// Default deployment: a ctx.fs provider, the policy plugin, then the tools.
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() }) // @deepseek-ai/dsh-fs-local
await ctx.plugin(FsPolicy)                             // @deepseek-ai/dsh-fs-policy (policy gate)
await ctx.plugin(ToolFs)                                  // this package — registers read/write/edit

@deepseek-ai/dsh-fs-policy可选的:省略时,工具直接使用裸提供方(无条件写入/覆盖/编辑,无已观察状态)。加载这些工具的部署也应加载该插件,从而提供写入/编辑前读取行为。

配置

所有键均为可选;默认值是随产品交付的读取上限。

默认值 含义
readLimit 2000 一次 read 调用返回的默认和最大行数(工具 schema 将其声明为 limit 默认值)。
readMaxLineLength 2000 每行截断前保留的字符数(后缀会说明上限)。
readMaxBytes 51200 一次 read 调用所选行的字节上限;溢出时以「已达上限」footer 结束窗口。
readStreamMinSize 10485760 大于等于该大小或大小未知的文件采用流式读取,而不是整体加载到内存。

工具(schema 见文件系统工具 schema Agent Note

工具 参数 行为
read file_pathoffset?limit? 带行号的 UTF-8 内容和分页 footer。offset 从 1 开始;limit 默认为配置的 readLimit2000),上限也为该值。
write file_pathcontent 创建文件或完整替换文件。有策略插件时:覆盖现有文件要求先在未变版本上执行 read;创建新文件不需要。没有插件时:无条件执行。
edit file_path、非空 old_stringnew_stringreplace_all? 字面量替换;除非 replace_all 为 true,否则要求唯一匹配。有策略插件时:要求先执行 read(任何窗口),且文件此后未变。没有插件时:无条件执行。

字段名使用 snake_case,与 Claude Code 和现有 harness 工具 schema 一致。

规范成功值分别为:read{ path, offset, lines: [{ number, text }], totalLines }write{ path, operation: 'create' | 'update', before: string | null, after }edit{ path, before, after }。原生渲染器会保留下方带行号的读取结果和变更确认。write/edit 从这些规范值派生可回放的 diff 卡片元数据,read 派生可回放的读取卡片窗口 { path, offset, lines, totalLines, lang? };规范值本身仅限于本次执行,不会添加到 tool/result,只有派生出的呈现元数据会被持久化。

工具就是执行器;策略是事件门禁

工具注入策略服务,也不检查任何缓存。每个工具通过 ctx.fs.resolve(path, { cwd, signal }) 解析路径;它会传入调用 agent(智能体)的会话 cwd(exec.agent.session.header.cwd),使相对路径以会话工作区为基准解析并与 dsh-tool-bash 一致,同时把工具取消转发到解析过程(见每会话 cwd Agent Note)。随后执行:

  • read:一次 ctx.fs.stat(用于类型、大小路由和版本),随后调用 readText/streamText,构建行窗口,再发出 fs/observed,使用普通 ctx.emit。(1 次 stat。)
  • write:调用 ctx.waterfall('fs/write-intent', target, exec, () => undefined) 取得可选防护,然后调用 ctx.fs.writeText(target, content, intent),再发出 fs/observed。(0 次 stat。)
  • edit:调用 ctx.waterfall('fs/edit-intent', target, exec, () => undefined) 取得可选防护,然后调用 ctx.fs.editText(target, edit, intent),再发出 fs/observed。(0 次 stat。)

工具在每次分派中把 exec(工具执行上下文)作为不透明 actor 传入。默认 thunk 返回 undefined(不受约束的裸提供方)。加载 @deepseek-ai/dsh-fs-policy 后,它会占用单个决策槽:返回 createIfAbsent/replaceIfVersion/{ version } 或抛出 FS_NOT_OBSERVED,并在 fs/observed 时记录。后端错误(FsError)和抛出的 FS_NOT_OBSERVED 会流经 ToolRegistry.execute(),变成 isError 工具结果,并附带 { name, code }

ctx.fs.sandboxMode 表明提供方施加沙箱限制时,write/edit 会公开 sandbox_permissionsjustification,并通过 ctx.approval 解析经批准的重试。策略归属方会贡献与具体能力无关的常驻策略;工具结果仍保留操作特定的拒绝与重试引导。

fs/observed 发后即忘

fs/observed 在读取/写入/编辑已经成功之后,通过普通 ctx.emit 发出。监听器的契约是同步且只有副作用的记录器(@deepseek-ai/dsh-fs-policy 使用 WeakMap.set);工具不保护这次发出,因此监听器抛出会作为工具的 isError 结果出现。异步或可能失败的观察不属于该事件。

read 允许并发调度,因为其唯一变更是同步版本记录器。稍后的 writeedit 会在目标锁内重新检查版本,因此记录器竞态会以拒绝方式关闭;两个变更工具仍保持互斥。见并行工具调用 Agent Note

包根目录只导出 Cordis 插件契约(nameinjectConfigapply)。读取渲染(行窗口与输出格式化)位于 src/read-render.ts(不依赖 Cordis,单独进行单元测试);src/read.ts/write.ts/edit.ts 是工具执行器,src/index.ts 负责组合。

模型体验

系统提示词

模型看到的内容

该插件注册作用域内的每个请求都会收到下方独立注册的 read、write 与 edit 指导。作用域工具限制可以隐藏 schema,而不移除这些段。

Read 指导
Use the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.
Write 指导
Use the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-policy requires it) and prefer edit for targeted changes.
Edit 指导
Use the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-policy requires it), unless you just created or edited it in this session.

Token 影响

插件启用期间,每个请求支付固定指导成本;即使限制隐藏了一个或多个工具也一样。

KV Cache 影响

只要插件作用域和指导文本不变,前缀就保持稳定。工具限制不会移除该段,但插件启用或 dispose(资源释放)可能从该段开始使复用失效。

工具 schema

模型看到的内容

模型会看到已生成的 readwriteedit schema,参数使用 snake_case。作用域工具限制可以为某个 agent 移除任一定义。

Token 影响

该工具视图中的每个请求都支付固定 schema 成本。

KV Cache 影响

只要可见工具定义和顺序不变,前缀就保持稳定。注册生命周期或作用域限制可能从首个变化的 schema token 开始使复用失效。

读取结果

模型看到的内容

成功读取结果精确为 <path><displayPath></path>、换行、<type>file</type>、换行、<content>、形如 <lineNumber>: <text> 的编号行、一个空行、一条 footer 和 </content>。footer 精确为 (Output capped. Showing lines <start>-<end>. Use offset=<next> to continue.)(Showing lines <start>-<end> of <total>. Use offset=<next> to continue.)(End of file - total <total> lines)。长行结尾精确为 ... (line truncated to <max> chars)

Token 影响

读取输出受 readLimitreadMaxLineLengthreadMaxBytes 限制;保留的调用与结果会反复发送,直到上下文压缩(compaction)。

KV Cache 影响

仅追加;新增可见内容位于可复用请求前缀之后,不会使现有 KV Cache 条目失效。

写入与编辑结果

模型看到的内容

写入精确返回五行包络:<path><displayPath></path><type>file</type><content>Created fileUpdated file,以及 </content>。编辑精确返回 The file <displayPath> has been updated successfully.;对于 replace_all,精确返回 The file <displayPath> has been updated. All occurrences were successfully replaced.。完整写入或替换文本仍保留在 assistant 工具调用参数中。

Token 影响

成功文本很少,但大型变更参数和所有结果会反复发送,直到上下文压缩。

KV Cache 影响

仅追加;新增可见内容位于可复用请求前缀之后,不会使现有 KV Cache 条目失效。

工具错误

模型看到的内容

失败会规范化为 Error: <message>。本包稳定的校验和读取消息是 file_path must be a non-empty stringlimit must be less than or equal to <max>old_string must be a non-empty stringold_string and new_string must differcannot read "<path>": not foundcannot read "<path>": not a regular fileoffset <offset> is out of range for "<path>" (<total> lines);提供方和策略模板在各自包的 README 中逐字列出。防护变更失败还会在消息中携带恢复指令,由本包面向模型的错误包装追加:FS_STALE_VERSION(包括编辑目标缺失)追加 — re-read the file, then retryFS_NOT_OBSERVED 追加 — read the file, then retry;结构化错误码保持不变。

Token 影响

只有失败调用会添加这些保留 token。

KV Cache 影响

仅追加;新增可见内容位于可复用请求前缀之后,不会使现有 KV Cache 条目失效。

已知限制与暂缓事项

  • 未交付面向模型的目录列表工具ctx.fs.listDir 服务于 skill(技能)发现等提供方代码,同级 dsh-tool-fs-search 包则提供基于 bash 的 globgrep,而不是扩展文件系统 seam。
  • read 只处理 UTF-8 文本文件:二进制安全读取和 PDF/图像/多模态内容均延期处理;目录目标为 FS_NOT_REGULAR_FILE
  • 没有超时接口read/write/edit 不接受超时参数,也不声明 timeout-policy 预算;取消只通过 exec.signal 传递(见提供方理由)。