为 ctx.fs 提供本地文件系统后端,支持文件读写、目录列表、符号链接解析等12个FileSystem原语,适用于需要在本地文件系统上执行文件操作的 dsh plugin
ⓘ 此插件是大仓库 deepseek-ai/deepseek-harness 的子包,星数与活跃度统计的是整个仓库。
- 语言
- TypeScript
- License
- MIT
- 分支
- master
安装
$ dsh plugin --profile web add npm:@deepseek-ai/dsh-fs-local在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程
对话式安装
帮我安装 DeepSeek Harness 插件 deepseek-ai/deepseek-harness/packages/fs/fs-local:先查看仓库 https://github.com/deepseek-ai/deepseek-harness 确认安全性,然后执行安装命令并验证插件加载成功。
把这段指令粘贴给 DSH Web GUI 里的助手,由它代你完成安装与验证。
English | 中文
The local-filesystem implementation of the ctx.fs provider contract (@deepseek-ai/dsh-fs). Backs the twelve FileSystem primitives with the host filesystem; loading it as a plugin populates ctx.fs.
import { LocalFileSystem } from '@deepseek-ai/dsh-fs-local'
await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
// ctx.fs uses the local backend; load @deepseek-ai/dsh-fs-observation-policy for the
// freshness policy gate and @deepseek-ai/dsh-tool-fs to expose read/write/edit.
Behavior
resolve(path, opts?)— a relativepathresolves againstopts.cwdwhen the caller supplies one (the model-facing tools pass the calling agent's session cwd — see the per-session cwd Agent Note), elseconfig.cwd(defaultprocess.cwd()); an absolutepathignores both.opts.signalis checked before and after local resolution, while a remote sibling backend may use it to abort its round-trip. ThetargetKeyis the file'srealpath, so two input paths reaching the same file through symlinks share one identity, and writes/edits land on the link target (preserving the link). A not-yet-existing path uses the realpathed parent directory plus basename when the parent exists; only an unresolvable parent falls back to the absolute path.displayPathis the absolute (un-resolved) path.- Execution-world coordinates —
processPathexposes the target's canonical host path,fileUrlencodes that path through Node's platform-aware URL conversion, andcontainsuses platform path semantics to test identity or descendant containment without consumers parsingtargetKey. stat/lstat— return target metadata orundefinedwhen absent.statreportsFsInfofor an already resolved target (version= an opaque token derived from bigintdev:ino:size:mtimeNs:ctimeNs,typeoffile/directory/other, bytesize); path-shapedlstatreportsFsPathInfowithout following the final symlink and can therefore returnsymlink. Both check cancellation before and after their asynchronous metadata probe, so an abort that lands in flight reportsFS_ABORTEDrather than stale absence.readText/streamText— UTF-8 only.readTextreads the whole file;streamTextdecodes chunks so a huge file need not be held whole in memory and consumers can enforce their own retention bounds. Both reject invalid UTF-8 and NUL-byte binary samples (FS_NOT_TEXT) and non-regular targets. Thereadtool (@deepseek-ai/dsh-tool-fs) owns line windowing.readBytes— raw whole-file bytes with no decoding or binary rejection (theread_imagetool validates content through the attachment service). The required byte cap short-circuits on the stat size before any content I/O; the subsequent stream reads at most one byte beyond the cap, so a file growing after stat still failsFS_TOO_LARGEwithout unbounded buffering.listDir— lists one directory level in stablename.localeCompare()order. Each entry carries the child basename, type, resolved child target (displayPathunder the listed directory,targetKeyas the realpath identity), and cheap stat metadata (version, plussizefor regular files). It never opens or decodes file contents. Missing targets reportFS_NOT_FOUND, file/special-file targets reportFS_NOT_DIRECTORY, aborted calls reportFS_ABORTED, permission failures reportFS_PERMISSION_DENIED, and other listing or child metadata I/O failures reportFS_IO_ERROR. Broken/disappeared children are returned asotherwithout metadata, but permission/IO failures while resolving a child fail the whole listing with a structuredFsError.writeText— atomic: writes to a temp file opened exclusively (wx,0o600) inside a randomly-named private staging dir (0o700) next to the target, then fsyncs and publishes. An existing file's mode is preserved, while new files default to0o600; on Windows a new file inherits the destination directory's DACL, while replacement copies the target DACL onto the empty temp before writing and publishes throughReplaceFileWso the original access policy survives (Windows DACL preservation Agent Note). Theexpectedguard is OPTIONAL: omitting it unconditionally creates-or-overwrites;createIfAbsenthard-links the staged file into place as an atomic no-replace publication, so a regular file created after the initial probe is preserved and rejected withFS_NOT_OBSERVED, while a non-regular path entry is preserved and rejected withFS_NOT_REGULAR_FILE;replaceIfVersionreplaces only at the observed version (a missing target or mismatch isFS_STALE_VERSION). An overwrite returns the prior text as its contextual diff basis only when both the opened prior file and UTF-8 replacement are strictly belowconfig.diffBasisMaxBytes(default 10 MiB). The descriptor read enforces that limit even if an external writer replaces or changes the file size after the initial probe. Otherwise the provider returnsbefore: null, so presentation uses its whole-file fallback.editText— atomic literal read-modify-write over the same primitive, serialized per target by a mutation lock. Theexpectedguard is OPTIONAL: when supplied it verifies the version BEFORE literal matching (a stale edit reportsFS_STALE_VERSION, neverFS_EDIT_NOT_FOUND/FS_AMBIGUOUS_EDITagainst newer content); omitting it edits the current content unconditionally. A missing target reportsFS_STALE_VERSIONeither way. LF-normalizes for matching, restores the file's dominant CRLF/LF style, and rejects emptyoldString/ zero matches (FS_EDIT_NOT_FOUND) or ambiguous multi-matches withoutreplace_all(FS_AMBIGUOUS_EDIT).
The package-root SDK API is the default/named LocalFileSystem class plus Config. Raw I/O lives in src/fsio.ts (Cordis-free, independently unit-tested); src/index.ts is the thin service wiring.
Model Experience
Indirectly, through dsh-tool-fs, which renders this provider's line-windowed UTF-8 content, mutation acknowledgements, and exact provider messages in capped retained results while versions, atomic-write mechanics, and directory metadata remain internal.
KV Cache effect
No direct invalidation; the named consumer owns any request-prefix changes.
Known Limitations and Deferred Work
config.cwdis not a sandbox — it is a resolution default, not containment: absolute paths and..escape it. Enforce containment with a stricterctx.fsbackend or a permission plugin on thetools/executewaterfall (capability-seam Agent Note).- Version tokens depend on filesystem metadata — they combine device, inode, size, nanosecond mtime, and nanosecond ctime; a storage layer that cannot update any of those facts for a rewrite can still defeat the stale guard.
editTextholds the whole file (plus the edited copy) in memory — streaming exists only on the read path.- A sub-limit overwrite still buffers a contextual basis —
writeTextmay retain up to just belowconfig.diffBasisMaxBytesof prior text in addition to the caller-owned replacement; the bound does not cap the returnedaftervalue or presentation's whole-file fallback. - Binary detection is asymmetric — reads NUL-sample only the first 8192 bytes while edits scan the whole buffer, so a file with a late NUL reads fine but rejects edits.
- The per-target mutation lock is in-process only — guarded create still uses an atomic no-replace publication across processes, but replacement writers in another process are caught only when the optional version guard observes their metadata change; they are never serialized.
- Guarded creation requires hard-link support — filesystems or mounts that reject hard-link publication cannot serve
createIfAbsent; the provider preserves the missing target and reportsFS_IO_ERROR. - Post-commit cleanup is best effort — a successful publication remains successful if removal of its owner-only staging directory fails, leaving private residue for later operator cleanup.
收录徽章
[](https://deepseek-plugin.org/plugins/deepseek-ai/deepseek-harness/packages/fs/fs-local)把这段 markdown 粘贴到你的 GitHub README,链接回本插件详情页。徽章只声明已被本站收录,不代表安全认证。