Files
deepseek-harness/packages/fs/README.md
T

2.9 KiB

fs/ - filesystem capability family

The filesystem stack: a provider seam (text IO + atomic mutation with an optional version guard), a local implementation, a policy gate plugin (observed-state + read-before-edit + version-guarded write/edit), the model-facing file tools + executor, and the bash-backed discovery tools. All product packages.

Package Role ctx key
fs/ Provider seam: text IO + atomic mutation primitives (optional version guard); owns the fs/* policy events ctx.fs
fs-local/ Local-filesystem FileSystem implementation (registers ctx.fs)
fs-policy/ Policy gate plugin: observed-state + read-before-edit + version-guarded write/edit, via the fs/* event gate (no service — fs/* listeners)
tool-fs/ Model-facing read/write/edit tools AND the executor (reads via ctx.fs, owns read windowing, dispatches fs/*) (registers on ctx.tools)
tool-fs-search/ Model-facing glob/grep discovery tools when rg is available on the bash executor PATH, backed by fixed ripgrep commands through ctx.bash, NOT by ctx.fs provider methods (registers on ctx.tools)

The interface lives at fs/fs/. A sandboxed, remote, or project-scoped filesystem backend can replace fs-local without touching the seam, the policy gate, or the model-facing tool schemas. The policy (fs-policy/) is a plugin that participates only through the fs/* event gate, not a service the tool injects — so dropping it gracefully loses the policy and leaves the unconstrained bare provider rather than breaking the tool. A deployment that loads tool-fs/ is expected to also load it. Discovery (tool-fs-search/) deliberately does NOT extend the provider seam: search is a process-backed rg workflow on the bash executor, so filesystem backends stay free of a universal search contract; its tools register only when that executor can find rg, and its results are follow-up-readable when the bash workdir and the read root are the same workspace (the co-located deployment its README documents).

No timeouts on file IO

read/write/edit take no timeoutMs, and the provider seam arms no deadline — unlike bash and web (which consume @deepseek-ai/dsh-timeout) and the bash-backed glob/grep (whose declared timeoutMs is enforced by @deepseek-ai/dsh-timeout-policy): those are process-backed, where a deadline can really kill the work. A local syscall is best-effort-abortable at most: a timeout could not force an in-progress fsync/rename to stop, so a deadline here would be a knob that cannot deliver on its promise. Adding one would also be an implicit default in the exact place explicit-over-implicit forbids. Both reference agents (Claude Code, Codex) leave file IO untimed for the same reason; cancellation still propagates through the tool-execution signal for best-effort abort at syscall boundaries.