{"_id":"@buddhilive/dsh-tool-fs","name":"@buddhilive/dsh-tool-fs","dist-tags":{"alpha":"0.1.2-alpha.3","latest":"0.1.2-alpha.3"},"versions":{"0.1.2-alpha.3":{"name":"@buddhilive/dsh-tool-fs","description":"Model-facing filesystem tools (read, write, edit) over the DeepSeek Harness filesystem seam (ctx.fs)","version":"0.1.2-alpha.3","publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/Buddhilive/buddhi-ai-harness.git","directory":"packages/fs/tool-fs"},"type":"module","main":"lib/index.js","types":"lib/types/index.d.ts","exports":{".":{"types":"./lib/types/index.d.ts","default":"./lib/index.js"},"./invariant":{"types":"./lib/types/invariant.d.ts","default":"./lib/invariant.js"},"./src/*":"./src/*","./package.json":"./package.json"},"license":"MIT","dependencies":{"diff":"^9.0.0","@deepseek-ai/schemastery":"^3.18.2"},"peerDependencies":{"@buddhilive/dsh-attachment":"^0.1.2-alpha.3","@buddhilive/dsh-fs":"^0.1.2-alpha.3","@buddhilive/dsh-llm":"^0.1.2-alpha.3","@buddhilive/dsh-sandbox":"^0.1.2-alpha.3","@buddhilive/dsh-session":"^0.1.2-alpha.3","@buddhilive/dsh-sandbox-policy":"^0.1.2-alpha.3","@buddhilive/dsh-invariants":"^0.1.2-alpha.3","@buddhilive/dsh-system-prompt":"^0.1.2-alpha.3","@buddhilive/dsh-tools":"^0.1.2-alpha.3","@buddhilive/dsh-user-approval":"^0.1.2-alpha.3","@deepseek-ai/cordis":"^4.0.2"},"devDependencies":{"@buddhilive/dsh-agent-loop-testkit":"^0.1.2-alpha.3","@buddhilive/dsh-agent":"^0.1.2-alpha.3","@buddhilive/dsh-agent-loop":"^0.1.2-alpha.3","@buddhilive/dsh-attachment":"^0.1.2-alpha.3","@buddhilive/dsh-fs":"^0.1.2-alpha.3","@buddhilive/dsh-fs-observation-policy":"^0.1.2-alpha.3","@buddhilive/dsh-invariants":"^0.1.2-alpha.3","@buddhilive/dsh-llm-deepseek":"^0.1.2-alpha.3","@buddhilive/dsh-fs-local":"^0.1.2-alpha.3","@buddhilive/dsh-llm":"^0.1.2-alpha.3","@buddhilive/dsh-sandbox":"^0.1.2-alpha.3","@buddhilive/dsh-sandbox-policy":"^0.1.2-alpha.3","@buddhilive/dsh-session":"^0.1.2-alpha.3","@buddhilive/dsh-system-prompt":"^0.1.2-alpha.3","@buddhilive/dsh-user-approval":"^0.1.2-alpha.3","@deepseek-ai/cordis":"^4.0.2","@buddhilive/dsh-tools":"^0.1.2-alpha.3","@buddhilive/dsh-session-projection":"^0.1.2-alpha.3"},"_id":"@buddhilive/dsh-tool-fs@0.1.2-alpha.3","bugs":{"url":"https://github.com/Buddhilive/buddhi-ai-harness/issues"},"homepage":"https://github.com/Buddhilive/buddhi-ai-harness#readme","_integrity":"sha512-W+JfCo1HXZ+hgA7TNFo8ZN2fw6ti5X0zbEmNjS5KffsxZ/iOeVJ8Tq2Bt9LVKYlubkn2rAXeRD/btsQsHpc0Cg==","_resolved":"C:\\DevDojo\\Buddhi\\buddhi-ai-harness\\dist\\npm\\buddhilive-dsh-tool-fs-0.1.2-alpha.3.tgz","_from":"file:C:/DevDojo/Buddhi/buddhi-ai-harness/dist/npm/buddhilive-dsh-tool-fs-0.1.2-alpha.3.tgz","_nodeVersion":"24.13.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-W+JfCo1HXZ+hgA7TNFo8ZN2fw6ti5X0zbEmNjS5KffsxZ/iOeVJ8Tq2Bt9LVKYlubkn2rAXeRD/btsQsHpc0Cg==","shasum":"a69ea89e6b7059bfdbe1eea6691298d8befe2c02","tarball":"https://registry.npmjs.org/@buddhilive/dsh-tool-fs/-/dsh-tool-fs-0.1.2-alpha.3.tgz","fileCount":19,"unpackedSize":114278,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDYgUMBOP/qcy3b6xfRWyqPabdGwBDjGTfHAc3mNpoSzgIhAP4V8YOf+i5287VGjh7HFVKEOsrPZ1Yn0d4dUWMe4s8i"}]},"_npmUser":{"name":"buddhilive","email":"visitbudkavin@gmail.com"},"directories":{},"maintainers":[{"name":"buddhilive","email":"visitbudkavin@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/dsh-tool-fs_0.1.2-alpha.3_1788165864043_0.8593194574425971"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-31T08:44:23.817Z","0.1.2-alpha.3":"2026-08-31T08:44:24.172Z","modified":"2026-08-31T08:44:24.417Z"},"maintainers":[{"name":"buddhilive","email":"visitbudkavin@gmail.com"}],"description":"Model-facing filesystem tools (read, write, edit) over the DeepSeek Harness filesystem seam (ctx.fs)","homepage":"https://github.com/Buddhilive/buddhi-ai-harness#readme","repository":{"type":"git","url":"git+https://github.com/Buddhilive/buddhi-ai-harness.git","directory":"packages/fs/tool-fs"},"bugs":{"url":"https://github.com/Buddhilive/buddhi-ai-harness/issues"},"license":"MIT","readme":"---\ndescription: \"面向模型的 read、read_image、write 与 edit 工具：供组合或排查 agent 文件系统访问的用户与维护者使用。\"\nkind: \"package-reference\"\n---\n\n# @buddhilive/dsh-tool-fs\n\n[English](README.md) | 中文\n\n## 概述\n\n`dsh-tool-fs` 提供面向模型的文件系统工具——`read`、`read_image`、`write` 与 `edit`——及其执行器。借助它们，模型可以带行号读取文件、原子地创建或替换文件，并执行有针对性的字面量编辑；结果都有上限，失败携带稳定错误码与恢复指令，所有文件操作都运行在已挂载的 `ctx.fs` 后端之上。编辑前读取策略位于独立插件（`dsh-fs-observation-policy`）中，因此省略它只会得到无条件、依然原子的变更。`read_image` 在持久附件存储已挂载时出现，并且只在路由模型声明图片输入时允许执行。当模型需要读取、创建、替换或编辑 UTF-8 文本文件时选择本包；发现工具（`glob`/`grep`）在同级包中。\n\n## 目录\n\n- [使用本包](#use-this-package)\n- [理解实现](#understand-the-implementation)\n- [进一步探索](#further-exploration)\n- [模型体验](#model-experience)\n- [已知限制与延期工作](#known-limitations-and-deferred-work)\n- [开发备注](#dev-note)\n\n-----\n\n<a id=\"use-this-package\"></a>\n## 使用本包\n\n在 `ctx.fs` 后端之后挂载工具，并在需要先读后写/编辑行为时挂载策略插件。模型随后获得带行号的读取、原子的写入与编辑，以及——挂载附件存储时——图像读取；每个结果都有上限，失败携带稳定错误码与恢复指令。\n\n### 最小组合\n\n一个后端、策略插件，然后是工具；附件存储为可选，用于启用 `read_image`。\n\n```yaml\n- name: '@buddhilive/dsh-fs-local'\n- name: '@buddhilive/dsh-fs-observation-policy'\n- name: '@buddhilive/dsh-tool-fs'\n```\n\n策略插件是可选的：省略时，工具直接使用裸提供方（无条件写入、覆盖与编辑，无已观察状态）。加载这些工具的部署也应加载该插件，从而提供写入/编辑前读取行为。`read_image` 只在持久 `ctx.attachments` 服务已挂载时注册；执行时还拒绝确切模型未声明图像输入的路由，因此文本路由的持久历史不会出现图像块。\n\n### 工具\n\n| 工具 | 参数 | 行为 |\n|---|---|---|\n| `read` | `file_path`、`offset?`、`limit?` | 带行号的 UTF-8 内容与分页 footer；`offset` 从 1 开始，`limit` 默认为配置的 `readLimit`，上限也为该值 |\n| `read_image` | `file_path` | 读取并持久保存 PNG/JPEG/WebP/GIF 源图；规范化可在下一次模型请求前缩小图片，因此模型无需先创建缩略图 |\n| `write` | `file_path`、`content` | 创建或完整替换文件；有策略插件时，覆盖要求先在未变版本上执行 `read`，创建不需要 |\n| `edit` | `file_path`、`old_string`、`new_string`、`replace_all?` | 字面量替换，除非 `replace_all` 为 true 否则要求唯一匹配；有策略插件时，要求先执行 `read` 且文件未变 |\n\n字段名使用 snake_case，与 Claude Code 和现有 harness 工具 schema 一致。成功返回紧凑信封——读取窗口、图像引用或 `Created file`/`Updated file` 确认——`write`/`edit` 还会派生可回放的 diff 卡片元数据供 UI 展示。\n\n### 配置\n\n所有键均为可选；默认值是随产品交付的读取上限。\n\n| 键 | 默认值 | 含义 |\n|---|---|---|\n| `readLimit` | `2000` | 一次 `read` 调用返回的默认和最大行数 |\n| `readMaxLineLength` | `2000` | 每行截断前保留的字符数 |\n| `readMaxBytes` | `51200` | 一次 `read` 调用所选行的字节上限；溢出时以「已达上限」footer 结束窗口 |\n| `readStreamMinSize` | `10485760` | 大于等于该大小或大小未知的文件采用流式读取，而不是整体加载到内存 |\n\n生成的[配置目录](../../../docs/config-catalog.zh.md#buddhilivedsh-tool-fs)是每个受支持字段及其 JSDoc 的穷尽式真源。\n\n### 策略与沙箱行为\n\n挂载策略插件后，`write` 与 `edit` 从 `fs/*` 意图槽位取得防护，因此未读目标或陈旧观察会以 `FS_NOT_OBSERVED` 或 `FS_STALE_VERSION` 及恢复指令失败。使用施加沙箱限制的后端（`fs-sandbox`）时，`write`/`edit` 还会公开 `sandbox_permissions` 与 `justification`；被拒绝的变更返回 `[sandbox: file access denied under <mode> mode]` 标记与同轮次升级提示，获批的重试可以在该次调用中加盖严格更宽的模式。\n\n### 失败与恢复\n\n失败被规范化为 `Error: <message>`，并为调用方保留结构化错误码。稳定消息包括 `file_path must be a non-empty string`、`limit must be less than or equal to <max>`、`cannot read \"<path>\": not found`、`cannot read \"<path>\": not a regular file`，以及图像路由拒绝 `cannot read \"<path>\" as an image: model \"<model>\" does not declare image input; switch to an image-capable model to read images`。防护变更失败会追加恢复指令：`FS_STALE_VERSION` 追加 `— re-read the file, then retry`，`FS_NOT_OBSERVED` 追加 `— read the file, then retry`。该次重新读取确认缺失后，`edit` 报告 `FS_NOT_FOUND` 而不会重复陈旧恢复指令，`write` 则使用防护创建。\n\n-----\n\n<a id=\"understand-the-implementation\"></a>\n## 理解实现\n\n<details>\n<summary>实现细节——点击展开</summary>\n\n本节解释工具套件背后的设计决策，并指出实现它们的代码位置；可观察行为已在[使用本包](#use-this-package)中完整说明。\n\n### 设计理念\n\n工具就是执行器；策略是事件门禁。工具不注入策略服务，也不检查任何缓存——每次变更都通过 `ctx.waterfall` 向单一意图槽位请求防护，每个操作只在成功后发出 `fs/observed`。读取恰好执行一次提供方 `stat`（类型与大小路由加观察到的版本）；变更一次也不执行，因为防护来自意图槽位，提供方在锁内重新检查。\n\n### 源码地图\n\n| 文件 | 职责 |\n|---|---|\n| [`src/index.ts`](src/index.ts) | 插件入口：`Config`、工具组合、`read_image` 附件门禁 |\n| [`src/read.ts`](src/read.ts) | `read` 执行器：一次 stat、流式决策、窗口构建、观察 |\n| [`src/read-image.ts`](src/read-image.ts) | `read_image` 执行器：路由与媒体类型门禁、有界字节、附件保存 |\n| [`src/write.ts`](src/write.ts) | `write` 执行器：意图 waterfall、原子写入、观察 |\n| [`src/edit.ts`](src/edit.ts) | `edit` 执行器：意图 waterfall、字面量编辑、观察 |\n| [`src/read-render.ts`](src/read-render.ts) | 不依赖 Cordis 的窗口构建与信封格式化 |\n| [`src/sandbox.ts`](src/sandbox.ts) | `write`/`edit` 共享的升权 API：策略解析与拒绝标记映射 |\n| [`src/error.ts`](src/error.ts) | 追加到 `FS_STALE_VERSION` 与 `FS_NOT_OBSERVED` 的面向模型恢复指令 |\n\n### 各工具流程\n\n四个工具共享同一种流程形态：用调用会话的 cwd 解析路径、运行适用的门禁、恰好执行一次提供方操作，并且只在成功后发出 `fs/observed`。`read` 与 `read_image` 为类型与大小路由付出一次 `stat`；`write` 与 `edit` 不执行 stat，因为防护来自意图槽位，提供方失败以类型化 `FsError` 结果呈现。各工具执行器位于 `src/read.ts`、`src/read-image.ts`、`src/write.ts` 与 `src/edit.ts`。\n\n### 观察与并发\n\n`fs/observed` 在操作成功之后通过普通 `ctx.emit` 发出；监听器的约定是同步且只有副作用的记录器，因此异步或可能失败的观察不属于该事件。`read` 允许并发调度，因为它唯一改变状态的操作是同步记录版本；稍后的 `write` 或 `edit` 会在目标锁内重新检查版本，因此记录器竞态会安全地失败，两个变更工具仍保持互斥。\n\n</details>\n\n-----\n\n<a id=\"further-exploration\"></a>\n## 进一步探索\n\n当包级约定不够用时阅读以下页面。它们从工具逐步进入它们所组合的约定、后端与策略。\n\n- [文件系统子系统](../../../docs/subsystems/filesystem.zh.md)——穷尽式提供方约定、策略事件与错误分类体系。\n- [dsh-fs](../fs/README.zh.md)——这些工具消费的 `ctx.fs` 约定。\n- [fs-local](../fs-local/README.zh.md)——这些工具运行于其上的宿主文件系统后端。\n- [fs-sandbox](../fs-sandbox/README.zh.md)——添加升权字段的沙箱强制后端。\n- [fs-observation-policy](../fs-observation-policy/README.zh.md)——通过 `fs/*` 事件防护变更的策略插件。\n- [生成工具目录](../../../docs/tool-catalog.zh.md#buddhilivedsh-tool-fs)——本包注册的穷尽式 schema。\n\n-----\n\n<a id=\"model-experience\"></a>\n## 模型体验\n\n### 系统提示词\n\n#### 模型看到的内容\n\n该插件注册作用域内的每个请求都会收到下方独立注册的 read、write 与 edit 指导。作用域工具限制可以隐藏 schema，而不移除这些段。\n\n##### Read 指导\n\n```markdown\nUse 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.\n```\n\n##### Write 指导\n\n```markdown\nUse the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-observation-policy requires it) and prefer edit for targeted changes.\n```\n\n##### Edit 指导\n\n```markdown\nUse 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-observation-policy requires it), unless you just created or edited it in this session.\n```\n\n#### Token 影响\n\n插件启用期间，每个请求支付固定指导成本；即使限制隐藏了一个或多个工具也一样。\n\n#### KV Cache 影响\n\n只要插件作用域和指导文本不变，前缀就保持稳定。工具限制不会移除该段，但插件启用或 dispose（资源释放）可能从该段开始使复用失效。\n\n### 工具 schema\n\n#### 模型看到的内容\n\n模型会看到已生成的 [`read`、`read_image`、`write` 和 `edit` schema](../../../docs/tool-catalog.zh.md#buddhilivedsh-tool-fs)，参数使用 snake_case。图片工具只在持久附件存储已挂载时出现；schema 本身与路由无关，严格门禁在执行时拒绝。作用域工具限制可以为某个 agent 移除任一定义。\n\n#### Token 影响\n\n该工具视图中的每个请求都支付固定 schema 成本。\n\n#### KV Cache 影响\n\n只要可见工具定义和顺序不变，前缀就保持稳定。注册生命周期或作用域限制可能从首个变化的 schema token 开始使复用失效。\n\n### 读取结果\n\n#### 模型看到的内容\n\n成功读取结果精确为 `<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)`。读取缺失目标仍返回 `FS_NOT_FOUND`，但会为调用会话记录确认缺失；外部删除的文件被重新读取后，重试的 `write` 可以通过提供方的不替换防护安全地重新创建该文件。\n\n#### Token 影响\n\n读取输出受 `readLimit`、`readMaxLineLength` 与 `readMaxBytes` 限制；保留的调用与结果会反复发送，直到上下文压缩（compaction）。\n\n#### KV Cache 影响\n\n仅追加；新增可见内容位于可复用请求前缀之后，不会使现有 KV Cache 条目失效。\n\n### 图像读取结果\n\n#### 模型看到的内容\n\n成功的 `read_image` 返回 `<path><displayPath></path>`、`<type>image</type>` 和写明媒体类型、规范化尺寸与字节数的 `<content>` 信封，随后是作为原生图像块的图像本身。结果会随持久引用写入会话日志，然后才进入下一次模型请求。\n\n#### Token 影响\n\n图像在之后每次请求中都会计费，直到压缩。每次调用都独立受附件存储的 `maxImageBytes`/`maxImagePixels`/`maxImageDimension` 约束；重复成功调用会在历史中累积，内容寻址只去重存储的字节，不去重每次请求的 token 成本。\n\n#### KV Cache 影响\n\n仅追加；新可见内容跟在可复用请求前缀之后，不会使既有 KV 缓存条目失效。\n\n### 写入与编辑结果\n\n#### 模型看到的内容\n\n写入精确返回五行包络：`<path><displayPath></path>`、`<type>file</type>`、`<content>`、`Created file` 或 `Updated file`，以及 `</content>`。编辑精确返回 `The file <displayPath> has been updated successfully.`；对于 `replace_all`，精确返回 `The file <displayPath> has been updated. All occurrences were successfully replaced.`。完整写入或替换文本仍保留在 assistant 工具调用参数中。\n\n#### Token 影响\n\n成功文本很少，但大型变更参数和所有结果会反复发送，直到上下文压缩。\n\n#### KV Cache 影响\n\n仅追加；新增可见内容位于可复用请求前缀之后，不会使现有 KV Cache 条目失效。\n\n### 工具错误\n\n#### 模型看到的内容\n\n失败会规范化为 `Error: <message>`。本包稳定的校验和读取消息是 `file_path must be a non-empty string`、`limit must be less than or equal to <max>`、`old_string must be a non-empty string`、`old_string and new_string must differ`、`cannot read \"<path>\": not found`、`cannot read \"<path>\": not a regular file`、`offset <offset> is out of range for \"<path>\" (<total> lines)`、`cannot read \"<path>\": read_image only accepts PNG/JPEG/WebP/GIF paths`、`cannot read \"<path>\" as an image: model \"<model>\" does not declare image input; switch to an image-capable model to read images`，以及类型不匹配的修复消息 `cannot read \"<path>\": the <ext> extension declares <type>, but the bytes use a different image format; rename the file to match its actual format if it is PNG/JPEG/WebP/GIF, or convert it to one of those formats`。16-bit 转换失败会报告 `cannot read \"<path>\": the 16-bit PNG could not be converted to the normalized 8-bit sRGB form; convert it to an 8-bit PNG/JPEG/WebP and retry`。提供方和策略模板在各自包的 README 中逐字列出。防护变更失败还会在消息中携带恢复指令，由本包面向模型的错误包装追加：`FS_STALE_VERSION` 追加 `— re-read the file, then retry`，`FS_NOT_OBSERVED` 追加 `— read the file, then retry`；结构化错误码保持不变。该次重新读取确认缺失后，`edit` 会报告 `FS_NOT_FOUND`，而不会重复陈旧恢复指令；`write` 则使用带防护的创建。\n\n#### Token 影响\n\n只有失败调用会添加这些保留 token。\n\n#### KV Cache 影响\n\n仅追加；新增可见内容位于可复用请求前缀之后，不会使现有 KV Cache 条目失效。\n\n## 已知限制与延期工作\n\n<a id=\"known-limitations-and-deferred-work\"></a>\n\n\n这些限制说明工具套件何时不合适，或何时需要特别的运维注意。它们是当前包约束，不是通用文件系统对比或任务积压。\n\n- **未交付面向模型的目录列表工具**：`ctx.fs.listDir` 服务于 skill（技能）发现等提供方代码，同级 `dsh-tool-fs-search` 包则提供基于 ripgrep 的 `glob` 与 `grep`，而不是扩展文件系统 seam。\n- **`read` 只处理 UTF-8 文本文件**：图像使用独立的、按扩展名路由的 `read_image` 工具；PDF、音频和视频仍延期处理。目录目标为 `FS_NOT_REGULAR_FILE`。\n- **媒体类型按扩展名声明**：扩展名选择声明类型，附件存储的魔数校验保持权威；扩展名错误但格式正确的图像会得到改名修复提示，而不是被嗅探接受。\n- **工具结果卡片没有内嵌图像预览**：UI 表面以通用形式渲染图像结果（持久引用而非像素）；内嵌渲染延后到 UI 包处理。\n- **没有附件区域工具**：agent 在拥有文件系统路径时可以通过其他可用工具裁剪图片；没有路径的粘贴或拖入图片无法按更高分辨率重新读取。\n- **没有超时接口**：`read`/`write`/`edit` 不接受超时参数，也不声明超时预算；取消只通过 `exec.signal` 传递（见[提供方理由](../README.zh.md)）。\n\n<a id=\"dev-note\"></a>\n### 开发备注\n\n<details>\n<summary>维护者的工作上下文——点击展开</summary>\n\n无。\n\n</details>\n","readmeFilename":"README.zh.md","_rev":"1-53eb35fda5cd00af7e980c604e594205"}