{"_id":"@buddhilive/dsh-fs-local","name":"@buddhilive/dsh-fs-local","dist-tags":{"alpha":"0.1.2-alpha.3","latest":"0.1.2-alpha.3"},"versions":{"0.1.2-alpha.3":{"name":"@buddhilive/dsh-fs-local","description":"Local-filesystem implementation of 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/fs-local"},"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","peerDependencies":{"@buddhilive/dsh-fs":"^0.1.2-alpha.3","@buddhilive/dsh-invariants":"^0.1.2-alpha.3","@deepseek-ai/cordis":"^4.0.2"},"dependencies":{"koffi":"^3.1.0","@deepseek-ai/schemastery":"^3.18.2"},"devDependencies":{"@buddhilive/dsh-fs":"^0.1.2-alpha.3","@buddhilive/dsh-invariants":"^0.1.2-alpha.3","@buddhilive/dsh-llm":"^0.1.2-alpha.3","@deepseek-ai/cordis":"^4.0.2"},"_id":"@buddhilive/dsh-fs-local@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-ZLXHOmxtzDFU5K8G7EOBdCjMcI0QWClBO1BKQr6JuyK7XbviPLTMf4QKm9xzimiWPJUmXcoMjDIxRa2y9VfaZg==","_resolved":"C:\\DevDojo\\Buddhi\\buddhi-ai-harness\\dist\\npm\\buddhilive-dsh-fs-local-0.1.2-alpha.3.tgz","_from":"file:C:/DevDojo/Buddhi/buddhi-ai-harness/dist/npm/buddhilive-dsh-fs-local-0.1.2-alpha.3.tgz","_nodeVersion":"24.13.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-ZLXHOmxtzDFU5K8G7EOBdCjMcI0QWClBO1BKQr6JuyK7XbviPLTMf4QKm9xzimiWPJUmXcoMjDIxRa2y9VfaZg==","shasum":"cdce269b3426259c503f9fd00cfa1ceb2bfd170c","tarball":"https://registry.npmjs.org/@buddhilive/dsh-fs-local/-/dsh-fs-local-0.1.2-alpha.3.tgz","fileCount":11,"unpackedSize":77110,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAxLYz5oodbm5rh26k0td95Kc9tqjMeKT6CKsQ8W5fV4AiAeKZAa+ioQ72uKaHyIU9EbosmWRMDg6eKRnttkFoiWXg=="}]},"_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-fs-local_0.1.2-alpha.3_1788165607089_0.040880859023519234"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-31T08:40:06.810Z","0.1.2-alpha.3":"2026-08-31T08:40:07.245Z","modified":"2026-08-31T08:40:07.572Z"},"maintainers":[{"name":"buddhilive","email":"visitbudkavin@gmail.com"}],"description":"Local-filesystem implementation of 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/fs-local"},"bugs":{"url":"https://github.com/Buddhilive/buddhi-ai-harness/issues"},"license":"MIT","readme":"---\ndescription: \"`ctx.fs` 的宿主文件系统后端：面向选择或排查本地文件访问的部署方与维护者。\"\nkind: \"package-reference\"\n---\n\n# @buddhilive/dsh-fs-local\n\n[English](README.md) | 中文\n\n## 概述\n\n`dsh-fs-local` 在宿主文件系统上实现 `ctx.fs` 文件系统约定（[`dsh-fs`](../fs/README.zh.md)）：把它作为插件加载后，`ctx.fs` 就拥有真实的文件访问能力——针对本机文件的解析、读取、列出、原子写入与字面量编辑。相对路径从可配置的基准目录解析，经不同路径或符号链接到达的同一文件共享一个身份。由于本后端共享宿主文件系统，它还可以把绝对宿主路径映射为此执行世界使用的进程路径。写入是原子的并保留文件权限；可选版本防护让陈旧覆盖失败而不是静默覆盖。当进程需要直接、不受约束地访问宿主文件时选择它；需要约束变更时选择 `fs-sandbox`，文件状态属于远程执行世界时选择 `fs-e2b`。\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`、且可以接受进程本地实现时，挂载此后端。常用路径是显式的：加载后端、给出基准目录，然后面向模型的工具（`dsh-tool-fs`）或你自己的插件即可读取、写入和编辑文件。\n\n### 何时选择\n\n普通宿主文件访问请选择 `fs-local`。会话的写入与编辑必须限制在工作区与临时根目录内时，选择 [`fs-sandbox`](../fs-sandbox/README.zh.md)——它扩展此后端，只增加模式围栏。文件必须位于与子进程共享的远程执行世界时，选择 [`fs-e2b`](../../e2b/fs-e2b/README.zh.md)。`config.cwd` 只是解析默认值，不是约束边界：绝对路径与 `..` 都可以逃逸它。\n\n### 最小配置\n\n加载后端并给出基准目录；相对路径以它为基准解析，绝对路径忽略它。\n\n```yaml\n- name: '@buddhilive/dsh-fs-local'\n  config:\n    cwd: /absolute/path/to/workspace\n```\n\n| 字段 | 默认值 | 含义 |\n|---|---|---|\n| `cwd` | `process.cwd()` | 相对路径的基准目录 |\n| `diffBasisMaxBytes` | `10 MiB` | 每次覆写 diff 一侧的 UTF-8 字节上限；更大的覆写返回 `before: null` |\n\n生成的[配置目录](../../../docs/config-catalog.zh.md#buddhilivedsh-fs-local)是每个受支持字段及其 JSDoc 的穷尽式真源。\n\n### 你能做什么\n\n完整或流式读取任意普通 UTF-8 文本文件，按你选择的上限读取原始字节，并按稳定名称顺序列出一层目录。原子地创建或替换文件，并原子地应用字面量文本编辑；两个变更操作都按文件串行化，并发写入方绝不会交错。版本防护是可选的：省略它即无条件创建或覆盖，提供它则在文件自上次观察以来发生变化时失败。\n\n失败是携带稳定错误码的类型化 `FsError`——`FS_NOT_FOUND`、`FS_NOT_TEXT`（二进制内容）、`FS_STALE_VERSION`（自观察以来已变化）、`FS_EDIT_NOT_FOUND` 或 `FS_AMBIGUOUS_EDIT`（无唯一字面量匹配）等——因此调用方依据错误码分支，绝不解析消息文本。带防护的编辑遇到缺失目标时，无论哪种情况都报告 `FS_STALE_VERSION`。\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后端建立在三个想法之上：\n\n- **Realpath 身份。** `targetKey` 是文件的 `realpath`，因此经符号链接到达同一文件的两个输入路径共享一个身份，写入落在链接目标上，同时保留链接。\n- **原子发布。** 写入先写入目标旁私有暂存目录内的独占临时文件，执行 fsync 后发布；现有文件的 mode 会保留，Windows 上的 DACL 也会在替换后存活。\n- **单一变更临界区。** 每目标 FIFO 锁串行化读取→防护→写入窗口，并发写入与编辑因此被确定性排序——一方胜出，其余看到新版本并以陈旧拒绝。\n\n### 源码地图\n\n| 文件 | 职责 |\n|---|---|\n| [`src/index.ts`](src/index.ts) | 服务接线：`LocalFileSystem`、`Config`、每目标变更锁 |\n| [`src/fsio.ts`](src/fsio.ts) | 不依赖 Cordis 的原始 I/O：探测、读取、原子写入、字面量编辑、行尾处理 |\n| [`src/win32.ts`](src/win32.ts) | 原子替换的 Windows 专属 DACL 保留 |\n\n### 写入路径\n\n每次写入先探测目标、执行可选防护（`createIfAbsent` 或 `replaceIfVersion`）、在两侧都足够小时捕获有界的 `before` diff 基础、把新内容暂存到目标旁、fsync，然后原子发布。带防护的创建使用绝不替换并发创建者的硬链接发布，并以 `FS_NOT_OBSERVED` 拒绝它。\n\n### 编辑路径\n\n每次编辑先探测、在字面量匹配前校验版本防护（陈旧编辑因此报告 `FS_STALE_VERSION`，绝不会给出误导性的无匹配）、读取文件、以 LF 规范化执行字面量替换、恢复文件主要的行尾风格，然后重新发布——全部在每目标锁内完成。\n\n### 归属与不变式\n\n原始 I/O 不依赖 Cordis，在 `src/fsio.ts` 中独立单元测试；`src/index.ts` 保持为轻量接线。`config.cwd` 只是解析默认值——约束是 `fs-sandbox` 或 `tools/execute` 权限插件的工作。取消是尽力而为的 `AbortSignal`，在每次异步探测前后检查。\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-sandbox](../fs-sandbox/README.zh.md)——扩展本后端的沙箱强制后端。\n- [tool-fs](../tool-fs/README.zh.md)——消费 `ctx.fs` 的面向模型工具。\n- [fs-observation-policy](../fs-observation-policy/README.zh.md)——通过 `fs/*` 事件防护变更的策略插件。\n- [Windows DACL 保留笔记](../../../.agents/notes/implemented/bug-fix/2026-07-19-windows-atomic-write-dacl-preservation.zh.md)——原子替换为何复制目标的访问策略。\n\n-----\n\n<a id=\"model-experience\"></a>\n## 模型体验\n\n通过 `dsh-tool-fs` 间接产生影响；该消费方把本提供方带行窗口的 UTF-8 内容、变更确认与提供方消息原文渲染为有保留上限的结果，而版本、原子写入机制与目录元数据仍属内部细节。\n\n#### KV Cache 影响\n\n不会直接使缓存失效；具名消费方负责请求前缀的任何变化。\n\n## 已知限制与延期工作\n\n<a id=\"known-limitations-and-deferred-work\"></a>\n\n\n这些限制说明本地后端何时不合适，或何时需要特别的运维注意。它们是当前包约束，不是通用文件系统对比或任务积压。\n\n- **`config.cwd` 不是沙箱**：它是解析默认值，而非约束；绝对路径和 `..` 可以逃逸。请使用更严格的 `ctx.fs` 后端或 `tools/execute` waterfall（瀑布式事件）上的权限插件实施约束（见[能力 seam 笔记](../../../.agents/notes/implemented/architecture/2026-06-17-filesystem-capability-seam.zh.md)）。\n- **版本 token 依赖文件系统元数据**：它们组合设备、inode、大小、纳秒级 mtime 与纳秒级 ctime；如果存储层在重写时无法更新其中任何一项事实，仍可能绕过陈旧防护。\n- **`editText` 会把整个文件及编辑后的副本保存在内存中**：只有读取路径支持流式处理。\n- **低于上限的覆写仍会缓冲上下文基础**：`writeText` 除调用方持有的替换内容外，最多还会保留略低于 `config.diffBasisMaxBytes` 的旧文本；该上限不限制返回的 `after` 值，也不限制整文件展示回退。\n- **二进制检测不对称**：读取只对前 8192 字节执行 NUL 采样，编辑则扫描整个 buffer，因此 NUL 出现在后部的文件可以读取，但编辑会被拒绝。\n- **每目标变更锁仅限进程内**：即使跨进程，带防护的创建仍采用原子且不替换的发布方式；但只有当可选版本防护观察到元数据变化时，系统才能发现其他进程中的替换写入方，且绝不会将其串行化。\n- **带防护的创建要求支持硬链接**：拒绝硬链接发布的文件系统或挂载点无法支持 `createIfAbsent`；后端会使目标保持缺失状态并报告 `FS_IO_ERROR`。\n- **提交后清理采用尽力而为语义**：如果移除仅所有者可访问的暂存目录失败，成功发布仍视为成功，并留下私有残留供运维人员后续清理。\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-4a7c15eadde5d8faba541d091864f435"}