docs: trim generated prose

This commit is contained in:
Tianyi Cui
2026-07-12 03:36:43 +08:00
parent 3dca90261c
commit 75838e10b5
323 changed files with 2857 additions and 11833 deletions

View File

@@ -1,59 +1,8 @@
/**
* The filesystem provider seam (`ctx.fs`): an abstract service defining the
* text-storage primitives a backend provides — resolve a path into a stable
* target, stat its metadata, read/stream its text, write it atomically with an
* explicit intent, and apply a guarded literal edit — without saying HOW.
* Implementations subclass {@link FileSystem} and register themselves as the
* `fs` service; `@deepseek-ai/dsh-fs-local` (the host filesystem) is the first.
* Future implementations swap in sandboxed, remote, virtual, or project-scoped
* backends without touching the model-facing tool schemas
* (`@deepseek-ai/dsh-tool-fs`).
*
* The split mirrors the bash seam (`BashExecutor`/`LocalBashExecutor`). See the
* capability-seam RFC for why a swappable capability is three (here four)
* packages.
*
* ## This is a provider seam, not the policy layer
*
* `ctx.fs` is deliberately close to fsspec-style storage primitives. It owns
* UTF-8 decoding, binary/NUL rejection, atomic full-file writes, and the
* literal-edit critical section — but NOT line windows, numbered lines,
* rendered footers, or observed-state. Read windowing lives in the model-facing
* tool (`@deepseek-ai/dsh-tool-fs`); observed-state and read-before-write/edit
* are policy a plugin (`@deepseek-ai/dsh-fs-policy`) adds through the `fs/*`
* event gate. So a sandboxed/remote backend inherits no model-facing observation
* policy it has no business carrying.
*
* `editText` stays on this seam (not composed in the policy layer from a read
* plus a write) because version guard + literal match + atomic rewrite must
* stay inside one mutation critical section for correct error attribution and
* one-wins/one-stale concurrency, and a remote backend may implement it as a
* native compare-and-edit.
*
* ## The version guard is OPTIONAL — additive policy, not subtractive
*
* `ctx.fs` on its own is a complete, unconstrained text-storage seam: `read`
* reads, `write` unconditionally creates-or-overwrites, `edit` unconditionally
* replaces literal text in the current content. Both mutations take their
* version guard as an OPTIONAL argument — omit it for the unconstrained
* bare-provider behavior, supply it to guard against a concurrent change. The
* mutation runs inside the backend's per-target lock either way, so an
* unconditional write/edit is still atomic; "unconditional" drops the *version*
* precondition, not the atomicity. Observed-state, read-before-edit, and
* version-guarded write/edit are NOT provider behavior — they are policy a
* plugin (`@deepseek-ai/dsh-fs-policy`) adds on top by supplying the guard.
*
* ## The fs policy events live here, not in the policy plugin
*
* This package owns the `fs/write-intent`, `fs/edit-intent`, and
* `fs/observed` event vocabulary (see {@link Events}). The emitter is
* `@deepseek-ai/dsh-tool-fs` and the default listener is
* `@deepseek-ai/dsh-fs-policy`; the events live in the one package both
* already depend on, so the emitter shares a vocabulary with the policy listener
* without depending on the policy plugin. The events carry only `dsh-fs`
* vocabulary plus an opaque `object` actor — no model-facing concepts (line
* windows, numbered lines) and no agent/session owner structure leak down.
*
* The filesystem provider seam (`ctx.fs`): an abstract service defining the text-storage
* primitives a backend provides — resolve a path into a stable target, stat its metadata,
* read/stream its text, write it atomically with an explicit intent, and apply a guarded
* literal edit — without saying how.
* @module @deepseek-ai/dsh-fs
*/
@@ -92,44 +41,26 @@ declare module 'cordis' {
interface Events {
/**
* Single-slot decision: produce the write intent for the next
* {@link FileSystem.writeText}. The tool dispatches this as an unbound
* waterfall (no `this`) and supplies a default thunk returning `undefined`
* (unconditional create-or-overwrite — the bare provider). The
* `@deepseek-ai/dsh-fs-policy` policy listener returns `createIfAbsent`
* (unobserved actor) or `{ kind: 'replaceIfVersion', version: vObserved }`
* (observed) and does NOT call `next()` — one decision, not a composable
* chain. The slot is first-wins: the first non-`next()` decider (registration
* order, or `prepend`) occupies it; a second decider is a misconfiguration,
* not layering. `actor` is the opaque tool-execution context, never read here.
* Single-slot decision: produce the write intent for the next {@link
* FileSystem.writeText}.
*
* @param target - the resolved target about to be written.
* @param actor - the opaque tool-execution context the decider keys off.
* @mode waterfall
*/
'fs/write-intent'(target: FsTarget, actor: object | undefined, next: () => FsWriteIntent | undefined | Promise<FsWriteIntent | undefined>): Promise<FsWriteIntent | undefined>
/**
* Single-slot decision: produce the optional version guard for the next
* {@link FileSystem.editText}. The tool dispatches this as an unbound
* waterfall and supplies a default thunk returning `undefined` (unconditional
* edit of the current content — the bare provider; no `stat`). The
* `@deepseek-ai/dsh-fs-policy` policy listener returns
* `{ version: vObserved }`, or throws `FS_NOT_OBSERVED` if the actor is unset
* or has not observed the target. Does NOT call `next()`: one decision,
* first-wins (see {@link Events.'fs/write-intent'}).
* Single-slot decision: produce the optional version guard for the next {@link
* FileSystem.editText}.
*
* @param target - the resolved target about to be edited.
* @param actor - the opaque tool-execution context the decider keys off.
* @mode waterfall
*/
'fs/edit-intent'(target: FsTarget, actor: object | undefined, next: () => { version: FsVersion } | undefined | Promise<{ version: FsVersion } | undefined>): Promise<{ version: FsVersion } | undefined>
/**
* Record that an actor observed a target at a version, after a successful
* read/write/edit. Fire-and-forget (plain `emit`). A listener MUST be a
* synchronous, side-effect-only recorder (`@deepseek-ai/dsh-fs-policy`'s
* is a `WeakMap.set`): the tool does not guard the emit, so a listener that
* throws surfaces as the tool's `isError` result, and cordis `emit` does not
* await listener promises — async or fallible audit/telemetry does not
* belong here. No listener ⇒ nothing recorded. `actor` is the opaque
* tool-execution context.
* Record that an actor observed a target at a version, after a successful read/write/edit.
*
* @param target - the target that was read/written/edited.
* @param version - the version the actor now holds as its observation.
* @param actor - the observing tool-execution context; undefined records nothing useful.
@@ -140,34 +71,9 @@ declare module 'cordis' {
}
/**
* Abstract filesystem provider service. Subclass, implement the seven storage
* primitives, and load the subclass as a plugin — it registers as `ctx.fs` (one
* implementation per context; loading a second throws, cordis' standard
* duplicate-service behavior).
*
* Semantics every backend must honor:
* - {@link resolve} returns a stable {@link FsTarget}; the same underlying file
* reached by different input paths must yield the same `targetKey` so stale
* guards and target lookup agree across paths (e.g. through symlinks).
* - {@link stat} returns {@link FsInfo} metadata (never content) or `undefined`
* when the target is absent.
* - {@link readText}/{@link streamText} read the whole regular text file (the
* stream for large files); both own regular-file checks, UTF-8 decoding,
* binary/NUL rejection, and `FS_NOT_TEXT`.
* - {@link listDir} returns direct children of a directory in stable name order
* with resolved child targets and cheap metadata only. It never reads file
* contents. Missing targets throw `FS_NOT_FOUND`, non-directories throw
* `FS_NOT_DIRECTORY`, permission failures throw `FS_PERMISSION_DENIED`, and
* other backend I/O failures throw `FS_IO_ERROR`.
* - {@link writeText} is atomic temp-file + rename. `expected` is OPTIONAL:
* omit it for an unconditional create-or-overwrite (the bare-provider default),
* or supply a {@link FsWriteIntent} to guard the write.
* - {@link editText} verifies `expected.version` BEFORE literal matching (so a
* stale edit reports `FS_STALE_VERSION`, not `FS_EDIT_NOT_FOUND`/
* `FS_AMBIGUOUS_EDIT` against newer content), then applies literal replacement
* and writes atomically — all inside one mutation critical section. `expected`
* is OPTIONAL: omit it for an unconditional edit of the current content (a
* missing target still reports `FS_STALE_VERSION`).
* Abstract filesystem provider service. Subclass, implement the seven storage primitives, and
* load the subclass as a plugin — it registers as `ctx.fs` (one implementation per context;
* loading a second throws, cordis' standard duplicate-service behavior).
*/
export abstract class FileSystem extends Service {
constructor(ctx: Context) {
@@ -175,18 +81,10 @@ export abstract class FileSystem extends Service {
}
/**
* Resolve a model/plugin-supplied path into a stable {@link 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.
* Resolve a model/plugin-supplied path into a stable {@link 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.
*
* `opts.cwd` is the base directory a RELATIVE `path` resolves against; an
* absolute `path` ignores it. Omitted ⇒ the backend's own default base (the
* local backend uses its configured `cwd`). The CALLER supplies this — the
* seam does not read a session or agent — so a tool can resolve against the
* caller's per-session workspace (`exec.agent.session.header.cwd`) without the
* provider depending on `dsh-agent`/`dsh-session`. Mirrors how `dsh-tool-bash`
* defaults a bash `workdir` to the session cwd.
* @param path - the path to resolve; relative paths resolve against `opts.cwd`.
* @param opts - `cwd` overrides the backend's default base for relative paths.
* @returns the stable target; the same file yields the same `targetKey`.
@@ -243,11 +141,8 @@ export abstract class FileSystem extends Service {
abstract writeText(target: FsTarget, content: string, expected?: FsWriteIntent, signal?: AbortSignal): Promise<FsWriteOutcome>
/**
* Apply a literal edit to an existing UTF-8 text file. When `expected` is
* supplied, verifies `expected.version` as the stale guard BEFORE literal
* matching; OMITTING it edits the current content unconditionally (no version
* guard). Either way applies the replacement and writes atomically — one
* mutation critical section — and a missing target reports `FS_STALE_VERSION`.
* Apply a literal edit to an existing UTF-8 text file.
*
* @param target - the resolved target to edit.
* @param edit - the literal search/replace request.
* @param expected - the version guard; omit for an unconditional edit.

View File

@@ -1,21 +1,7 @@
/**
* Vocabulary for the filesystem provider seam (`ctx.fs`): the opaque
* target/version identities, the metadata `stat` returns, the write-intent
* and outcome shapes, the literal-edit request/outcome, and the typed error
* taxonomy.
*
* These types are shared by every backend (`@deepseek-ai/dsh-fs-local` and
* future sandboxed/remote backends) and by the policy layer
* (`@deepseek-ai/dsh-fs-policy`). They are deliberately a *text-storage*
* vocabulary half a level above byte-level fsspec: `readText`/`streamText` hand
* back decoded text, never raw bytes. Host-path assumptions stay out — `targetKey`
* and `version` are opaque branded tokens, and `displayPath` is the only field a
* consumer may show.
*
* Model-facing concepts (line windows, numbered lines, observed-state) do NOT
* live here; they belong to the consumer tool and the policy plugin
* (`@deepseek-ai/dsh-tool-fs` / `@deepseek-ai/dsh-fs-policy`).
*
* Vocabulary for the filesystem provider seam (`ctx.fs`): the opaque target/version
* identities, the metadata `stat` returns, the write-intent and outcome shapes, the
* literal-edit request/outcome, and the typed error taxonomy.
* @module @deepseek-ai/dsh-fs/types
*/
@@ -104,17 +90,11 @@ export interface FsDirEntry {
}
/**
* The explicit intent of a guarded {@link FileSystem.writeText} call.
* `createIfAbsent` creates a missing target and rejects an existing one with
* `FS_NOT_OBSERVED` (the path the policy plugin uses when the owner has no prior
* read). `replaceIfVersion` replaces only when the target exists at the observed
* version; a missing target or a version mismatch throws `FS_STALE_VERSION`.
*
* `writeText` takes this OPTIONALLY: omitting `expected` is the third,
* unconstrained state — an unconditional create-or-overwrite (the bare
* provider). The union itself carries only the two GUARDED intents; "no guard"
* is expressed by omission, so the write and edit mutations share one symmetric
* shape (`expected?`: omit = unconditional, present = guarded).
* The explicit intent of a guarded {@link FileSystem.writeText} call. `createIfAbsent` creates
* a missing target and rejects an existing one with `FS_NOT_OBSERVED` (the path the policy
* plugin uses when the owner has no prior read). `replaceIfVersion` replaces only when the
* target exists at the observed version; a missing target or a version mismatch throws
* `FS_STALE_VERSION`.
*/
export type FsWriteIntent =
| { kind: 'createIfAbsent' }