5.8 KiB
ctx.fs
FileSystem (abstract seam) — provided by @deepseek-ai/dsh-fs.
Abstract filesystem provider. Targets must preserve identity across aliases; reads expose regular UTF-8 text or typed errors, listings are stable and content-free, and mutations are atomic. Optional guards add stale protection without changing the unguarded provider contract.
ctx.fs.resolve(path, opts?)
abstract resolve(path: string, opts?: { cwd?: string; signal?: AbortSignal }): Promise<FsTarget>
Resolve a model/plugin-supplied path into a stable FsTarget. May perform I/O (a remote/sandboxed backend may need a round-trip to map a path to a stable identity), hence async even though the local backend only normalizes + realpaths.
path— the path to resolve; relative paths resolve againstopts.cwd.opts— optional cwd override and cancellation signal.
Returns the stable target; the same file yields the same targetKey.
ctx.fs.stat(target, signal?)
abstract stat(target: FsTarget, signal?: AbortSignal): Promise<FsInfo | undefined>
Return target metadata, or undefined when the target does not exist.
target— the resolved target to stat.signal— aborts the metadata round-trip.
Returns metadata only, never content; undefined for an absent target.
ctx.fs.lstat(path, opts?, signal?)
abstract lstat(path: string, opts?: { cwd?: string }, signal?: AbortSignal): Promise<FsPathInfo | undefined>
Return path metadata without following the final path component when it is a symbolic link. This is intentionally path-shaped, not target-shaped: resolve follows symlinks to produce the stable identity used by normal reads/writes, while lstat lets a consumer reject the path itself before that follow happens.
opts.cwd follows resolve's cwd rules. undefined means the path is absent.
path— the path to inspect; relative paths resolve againstopts.cwd.opts—cwdoverrides the backend's default base for relative paths.signal— aborts the metadata round-trip.
Returns metadata only, never content; undefined for an absent path.
ctx.fs.readText(target, signal?)
abstract readText(target: FsTarget, signal?: AbortSignal): Promise<string>
Read the whole regular text file as a single decoded string.
target— the resolved target to read.signal— aborts the read.
Returns the full decoded UTF-8 content.
ctx.fs.streamText(target, signal?)
abstract streamText(target: FsTarget, signal?: AbortSignal): Promise<AsyncIterable<string>>
Stream the whole regular text file as decoded text chunks (same text semantics as readText, for large files). The backend owns cross-chunk UTF-8 decoding and binary rejection so the policy layer never touches raw bytes.
target— the resolved target to read.signal— aborts the stream, including between chunks.
Returns the chunk iterable, decoded and validated like readText.
ctx.fs.listDir(target, signal?)
abstract listDir(target: FsTarget, signal?: AbortSignal): Promise<FsDirEntry[]>
List direct children of a directory in stable name order. Returns resolved child targets plus cheap metadata only; never reads file contents.
target— the resolved directory target.signal— aborts the listing.
Returns one entry per direct child, in stable name order.
ctx.fs.writeText(target, content, expected?, signal?)
abstract writeText(target: FsTarget, content: string, expected?: FsWriteIntent, signal?: AbortSignal): Promise<FsWriteOutcome>
Atomically create or replace UTF-8 text. expected guards intent and staleness; omission allows unconditional overwrite.
target— the resolved target to write.content— the full new file content.expected— the write intent guarding the write; omit for unconditional.signal— aborts before the atomic rename takes effect.
Returns the outcome, including the version the write produced.
ctx.fs.editText(target, edit, expected?, signal?)
abstract editText(target: FsTarget, edit: FsEditRequest, expected?: { version: FsVersion }, signal?: AbortSignal): Promise<FsEditOutcome>
Atomically edit literal text. When supplied, the version guard is checked before matching so stale content reports FS_STALE_VERSION; omission edits the current content without a freshness precondition.
target— the resolved target to edit.edit— the literal search/replace request.expected— the version guard; omit for an unconditional edit.signal— aborts before the atomic rename takes effect.
Returns the outcome, including the version the edit produced.